当前位置: 移动技术网 > IT编程>开发语言>Java > IntentService源码简析

IntentService源码简析

2020年07月14日  | 移动技术网IT编程  | 我要评论

IntentService源码分析

​ 首先还是介绍一下,IntentService是Service的子类,具有两个特点:**1.自动开启子线程执行任务;2.执行完成自动结束。**此外,一个IntentService可以start()多次,每次开启一个工作线程来执行,所有线程都停止后才可能调用onDestory()。

1.如何构成

​ 首先来看InteneService的成员变量,只有四个,非常简单。

    private volatile Looper mServiceLooper;           // 用于保存工作线程的Looper以创建Handler
    private volatile ServiceHandler mServiceHandler;  // Intent的最终消费者
    private String mName;                             // 服务名称
    private boolean mRedelivery;                      // 是否可重复发送

​ 其中,ServiceHandler是IntentService的内部类,继承自Handler。在其handleMessage()方法中调用了protected abstract void onHandleIntent(@Nullable Intent intent)然后调用Service的stopSelf()方法,使得服务可以自动结束

    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);                              // 停止服务
        }
    }

2.如何在子线程中执行

​ 那么,IntentService又是如何做到独立线程执行任务的呢?看看其onCreate()方法便知。

    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

​ HandlerThread是Android中定义的一个小工具类,可以说就是为Handler而生的Thread,看官方注解就能明白:Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

​ 而在上面的onCreate()方法中也确实是这么使用的,先创建一个HandlerThread然后获取其Looper对象,并用之创建Handler。我们都知道,Handler的handleMessage()方法是执行在它所绑定的Looper所在线程中的,因此上面代码中mServiceHandler处理消息也是在子线程thread了。

​ 最后看看HandlerThread类的主要代码,确实非常handy哈哈。由于在run()方法中执行了Loop.prepare(),所以要求先start()也就可以理解了。

public class HandlerThread extends Thread {
    Looper mLooper;                                   // 线程中的Looper
    private @Nullable Handler mHandler;               // 可以直接由HandlerThread创建对应的Handler并返回

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {                         // 同步块,保证同一IntentService多次start()顺序执行
            mLooper = Looper.myLooper();              //
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();                                //
        mTid = -1;
    }
}

3.消息如何传递

​ 然后来看下一个Intent如何封装在Message中进行传递。我们在使用IntentService时大概会先实现一个子类,覆盖onHandleIntent()方法取出Bundle进行处理,然后使用如下代码启动任务。

Intent it=new Intent(getActivity(), MyIntentService.class);
Bundle bd=new Bundle();
bd.putString("xxx",yyy);
it.putExtras(bd);
startService(it);

​ 那么就来看看IntentService的onStart()方法。

public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;               // 启动标识,用于stopSelf()的识别
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

// Handler类
public final Message obtainMessage()
{
    return Message.obtain(this);
}

​ 第一句实际上调用了父类Handler的方法,从Message缓存池中复用一个Message对象。然后将Intent对象保存在其obj中,最后调用Handler的sendMessage()方法。

​ 再简单提一下Handler消息机制的内容,该方法最终会调用mServiceLooper(从thread获取的Looper对象)中的MessageQueue中enqueueMessage()方法将msg加入到thread的消息队列中,而thread启动后其Looper.loop()循环就已开始,拿出消息队列中的msg对象进入处理阶段,也就是著名的msg.target.dispatchMessage(msg)了,这个target就是mServiceHandler,而dispatch~方法则会执行到handleMessage(),从msg中取出Intent并传给我们自己的处理逻辑,等待期执行完成,stopSelf()

public void handleMessage(Message msg) {
    onHandleIntent((Intent)msg.obj);
    stopSelf(msg.arg1);
}

本文地址:https://blog.csdn.net/SPACESTUDIO/article/details/107302229

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网