服务是运行在后台的,但它并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程,当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。并且所有的代码都是运行在主线程的,我们需要在服务的内部手动创建子线程,并在里面执行具体的任务。
1.多线程编程
1.1创建线程的两种方法
- 创建线程可以通过继承Thread类来实现
class MyThread extends Thread{
@Override
public void run(){
}
}
然后调用start()方法就可以启动线程。
new MyThred().start()
- 也可以通过实现Runnable接口(这种方法更普遍)
class MyThead implements Runnable{
@Override
public void run(){
}
}
如果想要启动线程:
MyThread myThread=new MyThread();
new Thread(myThread).start();
2.异步消息处理机制
Android中异步消息处理主要由四个部分组成:Message、Handler、MessageQueue和Looper。
-
Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。可以使用的字段有what、arg1、arg2、obj(可以携带一个Object对象)。 -
Handler
主要用来发送和处理消息的,发送消息使用sendMessage()方法,处理消息使用handleMessage()方法。 -
MessageQueue
消息队列,用于存放所有通过Handler发送的消息,这部分消息会一直存在于消息队列中,等待被处理,每个线程只会有一个MessageQueue对象。 -
Looper
Looper是每个线程中的MessageQueue管家,调用Looper的loop()方法后,就会进入到一个无限循环中,然后每发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法中去。每个线程也只有一个looper对象。
3.AsyncTask
如果我们像想要在子线程中对UI进行操作,还可以使用AsyncTask,AsyncTask是一个抽象类,在继承时我们可以为AsyncTask类指定3个泛型参数,3个参数用途如下:
- Params:在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
- Progress:后台执行任务,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
- Resulst:当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
例如:
class DownloadTask extends AsyncTask<Void,Integer,Boolean>{
}
第一泛型参数为Void,表示在执行AsyncTask的时候不需要传入参数给后台任务。第二个Integer,表示使用整型数据来作为进度显示单位,第三个泛型参数为Booolean,则表示使用布尔型数据来反馈执行结果。
我们一般需要重写以下几个方法:
-
onPreExecute()
该方法会在后台任务开始执行之前调用 -
doInBackground(params…)
该方法中所有的代码都会在子线程中运行,在该方法中不可以进行UI操作 -
onProgressUpdate
当在后台任务中调用了publishProgress(Progress…)方法后,该方法很快就会被调用,在这个方法中可以对UI进行操作。 -
onPostExecute(Result)
当后天任务执行完毕并通过return语句返回时,该方法就会被调用