前两篇文章介绍了AsyncTask与HandleThread,主要是针对Android的多线程编程。在这里补充下线程的知识。
线程是操作系统调度的最小单元,同时也是一种受限的资源(即不能无限制的创建和销毁,创建和销毁都会占用系统资源)。操作系统是通过时间片轮转的方式调度每个线程,因此不可能做到绝对的并行。
进程一般指一个执行单元,在PC或移动设备上指一个程序或者应用。一个进程可以包含一个或多个线程。
Android中的线程分为主线程和子线程。主线程处理界面相关的操作,子线程用于处理耗时操作。特性:在UI线程(主线程)中执行耗时操作,会出现ANR,即Android应用无响应。所以不能在程中执行耗时的操作。
IntentService的内容如下:
1.什么是IntentService?
2.IntentService的使用方式
3.IntentService源码分析
1.什么是IntentService?
IntentService是Android提供的一个抽象类,继承了Service,是一种特殊的Service。必须创建子类才能使用IntentService。它的启动方式和一般的service一样,同时在IntentService中有一个工作线程用来处理异步请求。
作用:处理异步请求,实现多线程。它有优先级较高,用执行高优先级的任务。
特点:用于执行后台耗时任务,执行完毕自动停止。
IntentServic的工作流程:
注意:多次创建IntentService,其后台任务是以队列的方式在IntentService的onHandleIntent回调方法中顺序执行,执行完毕后自动停止。
2.IntentService的使用方式
使用步骤如下:
① 定义IntentService的子类:传入线程名称、复写onHandleIntent()方法
② 在Manifest.xml中注册服务
③ 在Activity中开启Service服务
具体实例如下:
创建IntentService的子类,并实现onHandleIntent(),方法。
public class myIntentService extends IntentService {
/*构造函数*/
public myIntentService() {
//调用父类的构造函数
//构造函数参数=工作线程的名字
super("myIntentService");
}
/*复写onHandleIntent()方法*/
//实现耗时任务的操作
@Override
protected void onHandleIntent(Intent intent) {
//根据Intent的不同进行不同的事务处理
String taskName = intent.getExtras().getString("taskName");
switch (taskName) {
case "task1":
Log.i("myIntentService", "do task1");
break;
case "task2":
Log.i("myIntentService", "do task2");
break;
default:
break;
}
@Override
public void onCreate() {
Log.i("myIntentService", "onCreate");
super.onCreate();
}
/*复写onStartCommand()方法*/
//默认实现将请求的Intent添加到工作队列里
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("myIntentService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i("myIntentService", "onDestroy");
super.onDestroy();
}
}
在Manifest.xml文件中注册
<service android:name=".myIntentService">
<intent-filter>
<action android:name="cn.scu.finch"/>
</intent-filter>
</service>
最后在Activity中启动;
//同一服务只会开启一个工作线程
//在onHandleIntent函数里依次处理intent请求。
Intent i = new Intent("cn.scu.finch");
Bundle bundle = new Bundle();
bundle.putString("taskName", "task1");
i.putExtras(bundle);
startService(i);
Intent i2 = new Intent("cn.scu.finch");
Bundle bundle2 = new Bundle();
bundle2.putString("taskName", "task2");
i2.putExtras(bundle2);
startService(i2);
startService(i); //多次启动
结果为:
根据执行结果可以看到,它启动了多次,但任务都是顺序执行。
3.IntentService源码分析
// IntentService源码中的 onCreate() 方法
@Override
public void onCreate() {
super.onCreate();
// HandlerThread继承自Thread,内部封装了 Looper
//通过实例化HandlerThread新建线程并启动
//所以使用IntentService时不需要额外新建线程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
//获得工作线程的 Looper,并维护自己的工作队列
mServiceLooper = thread.getLooper();
//将上述获得Looper与新建的mServiceHandler进行绑定
//新建的Handler是属于工作线程的。
mServiceHandler = new ServiceHandler(mServiceLooper);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
// IntentService的handleMessage方法把接收的消息交给onHandleIntent()处理
// onHandleIntent()是一个抽象方法,使用时需要重写的方法
@Override
public void handleMessage(Message msg) {
// onHandleIntent 方法在工作线程中执行,执行完调用 stopSelf() 结束服务。
onHandleIntent((Intent) msg.obj);
//onHandleIntent 处理完成后 IntentService会调用 stopSelf() 自动停止。
stopSelf(msg.arg1);
}
}
// onHandleIntent()是一个抽象方法,使用时需要重写的方法
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
//把 intent 参数包装到 message 的 obj 中,然后发送消息,即添加到消息队列里
//这里的Intent 就是启动服务时startService(Intent) 里的 Intent。
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
//清除消息队列中的消息
@Override
public void onDestroy() {
mServiceLooper.quit();
}
我们来捋一下源码:IntentService本质是采用Handler + HandlerThread方式
首先是onCreat方法,通过HandlerThread单独开启一个名为IntentService的线程,创建一个名叫ServiceHandler的内部Handler,再将这两者绑定。这样IntentService中就可以使用 HandlerThread,并使用Handle传递消息。在ServiceHandler中的handleMessage方法中调用了抽象方法onHandleIntent(),这样,我们就能通过重写onHandleIntent()处理耗时任务了。
然后在onStartCommand()中传递给服务intent,顺序插入到工作队列中,发送给onHandleIntent(),通过onHandleIntent()来顺序处理Intent请求对象所对应的任务。
工作队列中的任务是顺序执行的。因为onCreate() 方法只会调用一次,所以只会创建一个工作线程,多次开启服务不会创建更多的线程,只是将消息添加到消息队列的等待执行。
但如果服务停止的话,会清空队列里的消息,不再执行。
最常使用场景:离线下载
一些对比:
IntentService与Service的区别
Service:依赖于应用程序的主线程(不是独立的进程 or 线程)
IntentService:创建一个工作线程来处理多线程任务
Service需要主动调用stopSelft()来结束服务,而IntentService在所有intent被处理完后,会自动关闭
IntentService与其他线程的区别
IntentService内部采用了HandlerThread实现,作用类似于子线程;
与后台线程相比,IntentService是一种后台服务,优势是:优先级高(不容易被系统杀死),从而保证任务的执行。