什么是服务?


服务(service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖任何的用户界面,即使应用被切换到后台或者用户重新启动了另一个程序,服务还是能够保持正常运行的。

不过需要注意的是,服务并不是运行在一个独立的进程里面,而是依赖于创建服务时所在的程序的进程,当某个程序的进程被杀掉的时候,所有依赖于这个进程的服务就都会被停掉!

当然也不能被服务的后台概念所迷惑,实际上所有的服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的,也就是说我们需要在服务的内部手动的床架子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞的情况。

Android多线程得先知道


在探究服务这点上我们首先要明白的是安卓的多线程,我们这里学习的也只是安卓多线程最基本以及简单的东西,虽然自己的水平也只是学习入门的水平,但是按照我对多线程这该耐心的理解,要仔细研究的话多线程里面的东西是不会少的,比如说线程之间的通信,由线程安全牵扯出的线程的各种锁等等,看最简单的,Android线程的基本用法:

// 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run();
// 具体的逻辑处理 }
}
/*
*
* 那我们改如何使用这个多线程呢?
* 其实也很简单,我们直接new 一个 MyThread类
* 然后调用它的start()方法,这样run方法里面的具体的操作就在子线程中执行了
* */

我们还有更好的方式来写多线程,这种继承的方式耦合度有点低,更多的时候我们是选择实现Runnable()接口的方式来定义一个线程,要是我们使用了这个方法来实现多线程之后我们调用的方式也就要发生改变

大概的思路还是: 我们初始化一个MyThread类,这个类实现一下 Runnable() 接口

我们再初始化一个Thread对象,但是在初始化的时候需要我们把New出来的MyThread类对象传入,在之后直接调用start()方法

那有没有更简单的方式来写呢?当然是有,也会说我们最常见的,要是你不想再去定义一个类,我们就使用下面匿名类的方式来写,代码如下:

// 使用匿名类的方式使用多线程
new Thread(new Runnable() {
@Override
public void run() { Log.d("ServiceMainActivity","我是在其他线程执行的任务")
}
}).start();

不安全的线程


Android的线程和我们iOS的线程是一样的也是不安全的,所以想要在子线程中更新UI是办不到的,这一点和我们iOS的一样,这时候就涉及到主线程和子线程之间的通信,该如何处理呢?

下面是我们在异步线程里面做的操作,在完成我们发送消息,在主线程接收到消息只有处理任务:

   // 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run(); // 具体的逻辑处理
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}

下面是我们在主线程做的操纵:

    public  static final int UPDATE_TEXT = 1;

    private  Handler handler = new Handler(){
// 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run(); // 具体的逻辑处理
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}
};

这样我们在异步和主线程之间建立起了通讯,其实在主线程和异步线程之间建立通讯的方式还有其他的方式,我们在接着看异步消息处理机制。

异步消息处理机制


在Android中的异步消息处理主要有四个部分组成: Message   Handler   MessageQueue    Looper

在上一节中,前面的Message和Handler在上一节中我们已经接触过了,而MessageQueue和Looper我们暂时还没有接触到,下面我们就对着四部分一点点的剖析一下。

1、Message

Message是在线程之间传递的消息,他可以在内部携带少量的信息,用于在不同的线程之间交换数据,前面的时候我们用到的只是简单的what字段,除此之外可以使用arg1和arg2字段类携带一些整形数据,使用obj字段可以携带一个object对象。

2、Handler

Handler 顾明思议也就是处理者的意思,它也主要是用于发送和处理消息的,发送消息一般都是使用Handler的sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到Handler的handleMessage()方法。

3、MessageQueue

MessageQueue 是消息队列的意思,它主要用于存放所有通过Handler发送的消息,这部分消息会一直存放在消息队列里面,等待被处理,每个线程中只会有一个MessageQueue对象。

4、Looper

Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法,就会进入到一个无限循环当中,然后每当发现MessageQueue中存放在一条消息,就会将它取出,并传递到Handler的handlerMessage()方法中,每一个线程中也只会有一个Looper对象。

我们了解了他们的基本概念之后我们也就可以看看下面的这张图了,Android异步消息处理流程图,通过这张流程图我们乐意更好的理解一下这个Android异步消息的处理流程,理解他们四个之间的关系,更好的裂解一下他们的概念:

 AsyncTask


为了更加方便的我们在子线程中对UI进行操作,Android还提供了拧一个好用的工具,比如AsyncTask,借助它既是你对异步消息的处理机制完全不了解,也可以十分简单的从子线程切换到主线程,当然他背后的实现原理还是使用了异步消息的处理机制的,只是Android帮我们分装好了而已。

AsyncTask首先是一个抽象类,所以我们想要使用它就必须创建一个子类去继承它,在继承的时候我们可以为AsyncTask类指定三个泛型参数:

* params  可用于在后台任务中使用

* Progress 后台执行任务的时候,界面要是要显示进度,可以使用这里指定的泛型作为进度单位

* Result  如果需要对结果进行参会,则使用这里指定的泛型作为返回值类型

除了上面的这三个参数,还有四个方法使我们在继承之后需要重写的:

1、onPreExecute()                  后台任务开始执行之前调用,用于进行一些界面上的初始化操作

2、doInBackground()              耗时操作

3、onProgressUpdate()           UI的操作

4、onPostExecute()                任务执行完毕并通过return语句进行返回时,这个方法很快被调用,返回的参数会违参数传递到此方法中,处理任务的收尾工作

当然想要启动个DownLoadTask任务,也只需要我们执行 new DownLoadTask().execute()方法即可。

Android学习--探究服务(一)的更多相关文章

  1. Android学习--探究服务(二)

    服务的基本用法 定义服务: 我们需要先创建服务,我们要使用就的利用一个类去继承它,然后重写它的几个方法,具体的我们看下面的代码: 我们重写了下面三个方法: * onCreate()           ...

  2. Android学习笔记--服务(Service)

    1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...

  3. Android学习之服务初体验

    •概念 Service(服务)是一个长期运行在后台,没有用户界面的应用组件,即使切换到另一个应用程序或者后台,服务也可以正常运行: 因此,服务适合执行一些不需要显示界面的后台耗时操作,比如下载网络数据 ...

  4. Android学习_服务

    一.           服务1.         Android多线程 每一个Android应用程序都会分别运行在一个独立的Dalvik(或ART?)虚拟机中,而每个虚拟机在启动时会运行一个UI主线 ...

  5. 【转】 Pro Android学习笔记(八十):服务(5):访问远程服务

    目录(?)[-] Client的AIDL文件 Client的代码 建立连接 请求服务 断开连接 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://bl ...

  6. 【转】 Pro Android学习笔记(八一):服务(6):复杂数据Parcel

    目录(?)[-] 自定义的Parcelable类 AIDL文件 服务的实现 Client的实现 同步和异步     文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处 ...

  7. 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件

    目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...

  8. 【转】 Pro Android学习笔记(七九):服务(4):远程服务的实现

    目录(?)[-] 远程服务的实现小例子 对外开放远程服务的接口 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flow ...

  9. 【转】 Pro Android学习笔记(七六):服务(1):local和remote

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...

随机推荐

  1. JS容易理解错误的地方

    在这端代码执行的末尾,你会不会hi变量回事函数中的hi了?你会不会认为这不是按引用传递了? 对值传递和引用传递产生质疑了? 1 var hi = {}; 2 function sayHello(hi) ...

  2. 【ZJ选讲·调整】

    给出n个点,m条有向边(带正权),起点S,终点T.(n<=2000,m<=30000) 再给出一个k,表示可以把最多k条边的权值调整为任意非负整数.(k<=100) 问是否可以通 ...

  3. POJ 3179 Corral the Cows

    Corral the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1352   Accepted: 565 De ...

  4. HDU 多校对抗赛 D Distinct Values

    Distinct Values Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  5. CentOS下SVN服务器的搭建使用

    转载自:http://ailurus.blog.51cto.com/4814469/1168481 SVN作为新一代代码版本管理工具,有很多优点,管理方便,逻辑明确,安全性高,代码一致性高.SVN数据 ...

  6. 解决设置了background-size: cover; 但是图片在ios下显示不完整的问题

    设置 background-size: % 99.9%:

  7. 【Foreign】采蘑菇 [点分治]

    采蘑菇 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output Sample Input 5 1 2 3 2 3 1 2 1 ...

  8. codefoeces 671 problem D

    D. Roads in Yusland standard output Mayor of Yusland just won the lottery and decided to spent money ...

  9. bzoj3786 星际探索 splay dfs序

    这道题 首先 因为他求的是当前点到根节点的路径和 我们可以将题目转换为括号序列的写法 将点拆为左括号以及右括号 左括号为正 右括号为负 这样题目就变为了求前缀和了 如果一个点是这个点的子树 那么他的左 ...

  10. npm install 报node-sass错误

    Node Sass could not -bit with Node.js .x Found bindings for the following environments: - OS X -bit ...