什么是服务?java
服务(service)是Android中实现程序后台运行的解决方案,它很是适合去执行那些不须要和用户交互并且还要求长期运行的任务。服务的运行不依赖任何的用户界面,即便应用被切换到后台或者用户从新启动了另外一个程序,服务仍是可以保持正常运行的。安全
不过须要注意的是,服务并非运行在一个独立的进程里面,而是依赖于建立服务时所在的程序的进程,当某个程序的进程被杀掉的时候,全部依赖于这个进程的服务就都会被停掉!多线程
固然也不能被服务的后台概念所迷惑,实际上全部的服务并不会自动开启线程,全部的代码都是默认运行在主线程当中的,也就是说咱们须要在服务的内部手动的床架子线程,并在这里执行具体的任务,不然就有可能出现主线程被阻塞的状况。异步
Android多线程得先知道ide
在探究服务这点上咱们首先要明白的是安卓的多线程,咱们这里学习的也只是安卓多线程最基本以及简单的东西,虽然本身的水平也只是学习入门的水平,可是按照我对多线程这该耐心的理解,要仔细研究的话多线程里面的东西是不会少的,好比说线程之间的通讯,由线程安全牵扯出的线程的各类锁等等,看最简单的,Android线程的基本用法:工具
// 线程的第一种写法,直接继承自Thread自定义咱们的MyThread类 class MyThread extends Thread{ @Override public void run() { super.run(); // 具体的逻辑处理 } } /* * * 那咱们改如何使用这个多线程呢? * 其实也很简单,咱们直接new 一个 MyThread类 * 而后调用它的start()方法,这样run方法里面的具体的操做就在子线程中执行了 * */
咱们还有更好的方式来写多线程,这种继承的方式耦合度有点低,更多的时候咱们是选择实现Runnable()接口的方式来定义一个线程,要是咱们使用了这个方法来实现多线程以后咱们调用的方式也就要发生改变oop
大概的思路仍是: 咱们初始化一个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咱们暂时尚未接触到,下面咱们就对着四部分一点点的剖析一下。
一、Message
Message是在线程之间传递的消息,他能够在内部携带少许的信息,用于在不一样的线程之间交换数据,前面的时候咱们用到的只是简单的what字段,除此以外可使用arg1和arg2字段类携带一些整形数据,使用obj字段能够携带一个object对象。
二、Handler
Handler 顾明思议也就是处理者的意思,它也主要是用于发送和处理消息的,发送消息通常都是使用Handler的sendMessage()方法,而发出的消息通过一系列的展转处理后,最终会传递到Handler的handleMessage()方法。
三、MessageQueue
MessageQueue 是消息队列的意思,它主要用于存放全部经过Handler发送的消息,这部分消息会一直存放在消息队列里面,等待被处理,每一个线程中只会有一个MessageQueue对象。
四、Looper
Looper是每一个线程中的MessageQueue的管家,调用Looper的loop()方法,就会进入到一个无限循环当中,而后每当发现MessageQueue中存放在一条消息,就会将它取出,并传递到Handler的handlerMessage()方法中,每个线程中也只会有一个Looper对象。
咱们了解了他们的基本概念以后咱们也就能够看看下面的这张图了,Android异步消息处理流程图,经过这张流程图咱们乐意更好的理解一下这个Android异步消息的处理流程,理解他们四个之间的关系,更好的裂解一下他们的概念:
AsyncTask
为了更加方便的咱们在子线程中对UI进行操做,Android还提供了拧一个好用的工具,好比AsyncTask,借助它既是你对异步消息的处理机制彻底不了解,也能够十分简单的从子线程切换到主线程,固然他背后的实现原理仍是使用了异步消息的处理机制的,只是Android帮咱们分装好了而已。
AsyncTask首先是一个抽象类,因此咱们想要使用它就必须建立一个子类去继承它,在继承的时候咱们能够为AsyncTask类指定三个泛型参数:
* params 可用于在后台任务中使用
* Progress 后台执行任务的时候,界面要是要显示进度,可使用这里指定的泛型做为进度单位
* Result 若是须要对结果进行参会,则使用这里指定的泛型做为返回值类型
除了上面的这三个参数,还有四个方法使咱们在继承以后须要重写的:
一、onPreExecute() 后台任务开始执行以前调用,用于进行一些界面上的初始化操做
二、doInBackground() 耗时操做
三、onProgressUpdate() UI的操做
四、onPostExecute() 任务执行完毕并经过return语句进行返回时,这个方法很快被调用,返回的参数会违参数传递到此方法中,处理任务的收尾工做
固然想要启动个DownLoadTask任务,也只须要咱们执行 new DownLoadTask().execute()方法便可。