参考:http://www.jianshu.com/p/8a3c44a9173a
IntentService:是Android里面的封装类,继承Service。
主要是用来处理异步请求,实现多线程。
若启动IntentService多次,那么每个耗时操作则以队列的方式在IntentService的onHandlerIntent回调方法中依次执行,执行完自动结束。
实现步骤:
1.定义IntentService的子类:传入线程名称,复用onHandleIntent方法
2.在Manifest.xml文件中注册服务
3.在Activity中开启Service服务
具体的代码:
/**
* 测试IntentService
*/
public class MyIntentService extends IntentService {
private static final String TAG = “MyIntentService”;
public MyIntentService() {
//调用父类的构造函数
//构造函数参数=工作线程的名字
super("MyIntentService");
}
/**
* 复写onHandleIntent,实现耗时的操作
* @param intent
*/
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG,"MyIntentService onHandleIntent");
//根据Intent的不同,处理不同的事务
String taskName = intent.getExtras().getString("taskName");
switch (taskName){
case "task1":
Log.i(TAG, "do task1");
break;
case "task2":
Log.i(TAG, "do task2");
break;
default:
break;
}
}
@Override
public void onCreate() {
Log.i(TAG,"MyIntentService onCreate");
super.onCreate();
}
/**
* 默认实现将请求的Intent添加到工作队列中
* @param intent 请求的Intent
* @param flags 请求的标志
* @param startId 开始id
* @return 返回值指示系统应该为服务当前启动状态使用什么语义。
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.i(TAG,"MyIntentService onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG,"MyIntentService onDestroy");
super.onDestroy();
}
}
注册:
<service
android:name=".service.MyIntentService"
android:exported="false"></service>
分别点击调用两个方法:
public void startIntentService1(){
Intent i = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("taskName","task1");
i.putExtras(bundle);
startService(i);
}
public void startIntentService2(){
Intent i2 = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("taskName","task2");
i2.putExtras(bundle);
startService(i2);
}
public void startIntentService1(){
Intent i = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("taskName","task1");
i.putExtras(bundle);
startService(i);
Intent i2 = new Intent(this,MyIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("taskName","task2");
i2.putExtras(bundle2);
startService(i2);
startService(i);//多次启动
}
从上面两种调用方法可以看出:如果方法执行完只有一个任务,那IntentService就会自己注销,执行onDestroy方法。如果一个方法中执行多次任务,就是等全部任务执行完成之后,才调用onDestroy方法,销毁服务。
源码分析:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper; //内部的Looper对象
private volatile ServiceHandler mServiceHandler; //维护的ServiceHandler
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
//IntentService的handleMessage方法将接收的消息交给onHandleIntent处理,
//onHandleIntent是一个抽象方法,使用时需要重写的方法
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@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);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
//把intent参数包装到message的obj中,然后发送信息,即添加到消息队列里
//这里的intent就是启动服务时startService(Intent)里的Intent
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
* 第一个人抽象方法,使用时需要重写的方法
intent:开启服务时,可以通过Intent传入需要执行的任务标志。
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
从源码中可以看出:IntentService本质就是采用Handler & HandlerThread方式:
1.通过HandlerThread单独开启一个名为IntentService的线程
2.创建一个名叫ServiceHandler的内部Handler
3.把内部Handler与HandlerThread所对应的子线程进行绑定
4.通过onStartCommand()传递给服务intent,一次插入到工作队列中,并逐个发送给onHandleIntent()
5.通过onHandleIntent来一次处理所有Intent请求对象所对应的任务
注意事项:
1.工作任务队列是顺序执行的:任务请求是逐个发送的,也就只能逐个执行
原因:onCreate方法只会调用一次,所以只会创建一个工作线程;工作线程不会多次创建,只是把消息加入消息队列中等待执行;如果服务停止,会清除消息队列中的信息,后续的事件得不到执行。
2.不建议通过bindService启动IntentService
原因:不会调用onStart或者onStartCommand方法,所以不会将消息发送到消息队列,那onHandleIntent将不会回调,就无法实现多线程的操作。
使用场景:线程任务需要按顺序、在后台执行,比如离线下载
IntentService与Service的区别:
1.Service依赖于应用程序的主线程,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR;而IntentService创建一个工作线程来处理多线程任务。
2.Service需要主动调用stopSelf()来结束任务。而IntentService不需要,所有任务处理完之后,会自动关闭服务。
3.IntentService为Service的onBind方法提供了默认实现:返回null;IntentService为Service的onStartCommand方法提供了默认的实现:将请求的intent添加到队列中。
IntentService与其他线程的区别:
1.IntentService内部采用了HandlerThread实现,作用类似于后台线程;
2.与后台线程相比,IntentService是一种后台服务,优势是:优先级高,从而保证任务的执行。