IntentService源码解析

来源:互联网 发布:c语言教学视频小甲鱼 编辑:程序博客网 时间:2024/06/13 07:08

一、简介

IntentService是作为处理异步请求的基类(以Intent对象表示),客户端发送请求, 通过android.content.Context.startService(Intent)的 方式把请求传递给IntentService。根据需要启动服务,依次使用线程池处理每个传过来Intent请求所对应的任务。

这样可以避免事务处理阻塞主线程(ANR)。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。 

以上是IntentService的官方定义,接下来我们来讲讲IntentService的特别之处,以及它跟Service又有什么联系和区别呢?
其实IntentService是一个具有消息循环特点的Service,它本身就是一个Service(继承自Service),Service有的特性它都有,当然,它也有Service没有的特性,这就是本篇博客要讨论的重点。我们需要知道:Service其实是在主线程中的,它在执行onCreate方法后打印的线程id就是主线程id,这就是说,如果你要在Service中编写耗时操作的话,程序很有可能会出现ANR的,这时候Android就给我们讲设计了IntentService这个东西~

话不多说,轻轻地直接抛出一个栗子吧:

  • 定义IntentService
/** * 自定义IntentService */public class MIntentService extends IntentService{    public MIntentService() {        super("");    }    @Override    protected void onHandleIntent(Intent intent) {        Log.i("tag", intent.getStringExtra("params") + "  " + Thread.currentThread().getId());    }}
  • 在AndroidManifest中注册Service
<service           android:name=".MIntentService"            />
  • 启动这个Service
/** * 定义TextView点击事件,启动IntentService服务 */title.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, MIntentService.class);                intent.putExtra("params", "ceshi");                startService(intent);            }        });

打印结果显示,可以发现当点击title组件的时候,service接收到了消息并打印出了传递过去的intent参数,同时显示onHandlerIntent方法执行的线程ID并非主线程,这是为什么呢?接下来就是源码的解析。

二、源码解析

IntentService源码:

public abstract class IntentService extends Service {    private volatile Looper mServiceLooper;    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,确保onHandleIntent不会阻塞主线程            onHandleIntent((Intent)msg.obj);            //在执行完了onHandleIntent之后,我们需要调用stopSelf(startId)声明某个job完成了            //当所有job完成的时候,Android就会回调onDestroy方法,销毁IntentService            stopSelf(msg.arg1);        }    }    public IntentService(String name) {        super();        //此处的name将用作线程名称        mName = name;    }    public void setIntentRedelivery(boolean enabled) {        mRedelivery = enabled;    }    @Override    public void onCreate() {        super.onCreate();         //创建HandlerThread,利用mName作为线程名称,HandlerThread是IntentService的工作线程        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");        thread.start();        mServiceLooper = thread.getLooper();        //将创建的HandlerThread所绑定的looper对象传递给ServiceHandler,        //这样我们创建的Handler就和HandlerThread通过消息队列绑定在了一起        mServiceHandler = new ServiceHandler(mServiceLooper);    }    @Override    public void onStart(@Nullable Intent intent, int startId) {        //在此方法中创建Message对象,并将intent作为Message的obj参数,        //这样Message与Intent就关联起来了        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        //将关联了Intent信息的Message发送给MessageQueue        mServiceHandler.sendMessage(msg);    }    @Override    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {        //IntentService重写了onStartCommand回调方法:在内部调用onStart回调方法        //所以我们在继承IntentService时,不应该再覆写该方法,即便覆盖该方法,我们也应该调用super.onStartCommand()        onStart(intent, startId);        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;    }    @Override    public void onDestroy() {        //在onDestroy方法中调用了Handler的quit方法,该方法会终止消息循环        mServiceLooper.quit();    }    @Override    @Nullable    public IBinder onBind(Intent intent) {        return null;    }    @WorkerThread    protected abstract void onHandleIntent(@Nullable Intent intent);}

首先我们要用IntentService就要重写它的抽象方法:onHandleIntent(),该方法是运行在子线程中的,为什么这么说呢?查看源码我们可以知道,当onCreate方法调用时,创建了一个IntentService的工作线程HandlerThread,取出工作线程中的Looper对象,并把它交给ServiceHandler处理,实例化ServiceHandler对象,该对象是一个继承了Handler的对象,消息的处理就是在这里面进行,同样,它用的方式是handleMessage()方法处理消息的。handler对象是依附于HandlerThread线程的,所以其handeMessage方法也是在HandlerThread线程中执行的,从而证实了我们刚刚例子中的一个结论。onHandlerIntent在子线程中执行。

那么发送消息有是在哪里呢?我们看onStart()方法,该方法关联了Message和Intent,并把Intent对象作为Message参数,并一起打包发送给MessageQueue。

三、总结

至此,IntentService发工作机制就已经很清晰了,它不过就是运用了消息队列机制来处理Intent对象的Service罢了~
下面我们用一张图简单地展示下:
这里写图片描述
结论:

  • IntentService是一个service,也是一个抽象类;

  • 继承IntentService需要实现其onHandlerIntent抽象方法;

  • onHandlerIntent在子线程中执行;

  • IntentService内部保存着一个HandlerThread、Looper与Handler等成员变量,维护这自身的消息队列;

  • 每次IntentService后台任务执行完成之后都会尝试关闭自身,但是当且仅当IntentService消息队列中最后一个消息被执行完成之后才会真正的stop自身;

原创粉丝点击