android中关于异步执行任务,有一个平时可能用得不算太多,但是又很有用的,那就是IntentService,顾名思义,它有是个服务,有服务的特性(后台进程),而且执行完异步任务之后会在合适的时间销毁自己,不会常驻后台服务,是比较智能的,用于做一些随应用启动而执行一次,或者是下载任务是很适用的。
这里我们来看看源码,IntentService的代码很少,很简单。
在第一次onCreat的时候,创建了一个HandlerThread。然后创建了一个handler,将handlerthread的loop传了进去,相当于这个handler的执行已经是异步了。
1: onCreat()
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
2: onStart
//在这里将传入的Intent信息以Message用handler发送出去。
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);//服务创建之后再次调用将会执行此方法,调用onStart,所以还是发送message
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
3: handler
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);//执行抽象方法
stopSelf(msg.arg1);//结束自己
}
}
这里差不多就看到结束了,那么,我们自己写个服务继承IntentService的话,就会实现onHandleIntent这个方法。然后我们只需要在里面去执行我们的异步操作就可以了。
使用:和服务请求使用一样。
//在需要的地方,直接开启服务即可
Intent intent=new Intent(this, MyIntentService.class);
intent.putExtra("type",MyIntentService.TYPE1);
startService(intent);
Intent intent2=new Intent(this, MyIntentService.class);
intent2.putExtra("type",MyIntentService.TYPE2);
startService(intent2);
/**
* 服务类
*/
public class MyIntentService extends IntentService {
public static final String TAG = MyIntentService.class.getSimpleName();
public static final String TYPE1 = "type1";
public static final String TYPE2 = "type2";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//因为发送是有先后的,handler是按队列的方式发送的,所以此方法的调用也有先后。依次执行了text1和text2
String str = intent.getExtras().getString("type");
if (str.equals(TYPE1)) {
text1();
} else if (str.equals(TYPE2)) {
text2();
}
}
private void text1() {
Log.i(TAG, "IntentService执行第一个任务");
}
private void text2() {
Log.i(TAG, "IntentService执行第二个任务");
}
}
使用是很简单的是吧?那么我们来看看运行效果:
,可以执行了正常服务开启之后的Log,然后执行IntentService里面的log,是顺序执行的。
然后来看看正在运行的服务:
,确实是只有那个正常开启的服务,也就是说继承自IntentService的服务执行完之后,销毁了自己,这就达到了效果。
说说注意的事项!官网也有介绍
1) 这个后台执行,不能影响UI,如果需要执行完毕之后更新UI,则需要用广播的方式来发送广播给界面更新UI,广播使用方式之一LoaclBroadCastManager 。
2) 这个是有执行顺序的,且执行过程中不能被中断,后面的消息需要等待前面执行完毕,这里不需要说明,handler是按队列来执行的,还有这里毕竟只使用了一个线程(handlerthread)。
private void text1() {
Log.i(TAG, "IntentService执行第一个任务");
Log.i(TAG,"准备休息10秒");
SystemClock.sleep(10*1000);//休息10秒
}
private void text2() {
Log.i(TAG, "IntentService执行第二个任务");
}
和前面执行顺序一样,先执行text1再执行text2,但是在执行text1的时候,我休息了10秒钟。看看输出:
确实是等待第一个执行完之后再执行的第二个。所以注意,IntentService需要执行一个能执行完成的任务,不然也就失去了它本身的意义。