欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IntentService源码简析

程序员文章站 2022-04-10 19:26:16
IntentService源码分析​首先还是介绍一下,IntentService是Service的子类,具有两个特点:**1.自动开启子线程执行任务;2.执行完成自动结束。**此外,一个IntentService可以start()多次,每次开启一个工作线程来执行,所有线程都停止后才可能调用onDestory()。1.如何构成​首先来看InteneService的成员变量,只有四个,非常简单。 private volatile Looper mServiceLooper;...

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