引言
相信大家在面试的时候都会被问到这个问题“说说Android中的多线程吧?”,那么对于这个问题我们可以回答的点就比较多了。比如Thread,Runnable,ThreadPoolExecutor,这些都是Java开发或者android开发中常用的线程处理方式,Android中为了保证线程安全,线程通信的效率,开发的便捷性,提供了HandlerThread,IntentService,AsyncTask。那么今天我们就来聊一聊IntentService。
Service和IntentService的区别与联系
我们都知道Service是可以在后台处理一些任务所创建的服务,并不是所有的任务都可以在后台进行处理,比如一些耗时的操作,如果我们不开启子线程去处理这些任务,还是会引起卡顿现象。同时,我们需要考虑的点就是ANR,ANR是指应用程序无响应。那么对于Android来说他有不同的情况会产生ANR,具体信息如下:
1\. 输入事件(按键和触摸事件)5s内没有被处理:Input event dispatching timed out
2\. BroadcaseReceiver的事件(onReceive方法)在规定时间内没处理完(前台广播10s,后台广播60s):Timeout of broadcast BroadcastRecord
3\. service前台20s,后台200s没有完成启动 :Timeout executing service
4\. ContentProvider的publish在10s内没进行完:Timeout publishing content providers
复制代码
从上面的知识点可以看到,Service中同样会发生ANR。所以在我们开发的过程中如果需要在Service中处理耗时的操作,就可以使用Android提供给我们的IntentService类。
IntentService是一个抽象类,其中的抽象方法onHandleIntent,由开发者自己去实现。
protected abstract void onHandleIntent(@Nullable Intent intent);
复制代码
IntentService会创建单独的worker线程来处理所有的intent请求,因此开发者无须处理多线程的问题,
IntentService内部持有一个HandlerThread,并通过HandlerThread来实现消息的处理
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
复制代码
IntentService会持有一个内部类ServiceHandler
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//通过抽象方法将当前消息的处理方式交给开发者执行
onHandleIntent((Intent)msg.obj);
//回调执行完成之后会执行stopSelf来停止当前Service
stopSelf(msg.arg1);
}
}
复制代码
stopSelf(msg.arg1)方法中的msg.arg1是一个int值,相当于一个请求的唯一标识。每发送一个请求,会生成一个唯一的标识,然后将请求放入队列,当全部执行完成(最后一个请求也就相当于getLastStartId == startId),或者当前发送的标识是最近发出的那一个(getLastStartId == startId),则会销毁我们的Service.
Service销毁的时候会执行onDestory()方法来停止IntentService内部的Looper循环
@Override
public void onDestroy() {
mServiceLooper.quit();
}
复制代码
IntentService的大致工作流程是
具体的IntentService源码如下,感兴趣的可以多看看,对照上面的流程进行分析
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
@UnsupportedAppUsage
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
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);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
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);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
复制代码
总结:其实IntentService的源码就是内部通过HandlerThread+Service来实现的,我个人觉得源码的阅读有利于我们对开发规范,开发思想上的提升,比如IntentService内部的抽象方法的运用,在平时我们的程序开发过程中也可以参考这种方式对代码进行书写。
作者:Android大师哥
链接:https://juejin.cn/post/6916543579372388366
来源:掘金
网友评论