IntentService源码解析

一、简介

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自身;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值