IntentService 使用及分析

IntentService

我们直接分析 IntentService 的源码,如下:

public abstract class IntentService extends Service {
    // Looper 对象
    private volatile Looper mServiceLooper;
    // Handler 对象
    private volatile ServiceHandler mServiceHandler;
    // 线程名称
    private String mName;
    private boolean mRedelivery;

    // Handler 内部类
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 抽象方法,子类覆写来执行具体的业务逻辑
            onHandleIntent((Intent)msg.obj);
            // 根据 startId 来销毁自身,如果多次启动服务,最后一次才会销毁成功并回调 onDestroy
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        // 设置线程名称
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // 创建 HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        // 启动
        thread.start();

        mServiceLooper = thread.getLooper();
        // 创建 Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        // 把相应信息封装成 Message 对象
        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 方法
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        // 退出循环,即销毁线程,回收资源
        mServiceLooper.quit();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        // 直接返回 Null
        return null;
    }

    // 抽象方法,子类覆写来执行具体的业务逻辑
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

实现逻辑分析:

  1. onCreate()方法中使用了一个 HandlerThread 来维护线程,传入 HandlerThread 内部维护的 Looper 来创建 ServiceHandler

  2. onStart() 方法中将 IntentstartId 作为参数封装进了 Message ,并发送到 ServiceHandler 来处理。

  3. onStartCommand() 方法直接调用第二步的 onStart() 方法。

  4. HandlerhandleMessage() 回调中会调用抽象方法 onHandleIntent() ,执行完之后,会调用 stopSelf(startId) 方法来销毁自身,每次启动服务时 startId 都会不一样,只有当最近的 onStart()startId 等于 stopSelf(startId) 时才会销毁成功并回调 onDestroy() 方法。比如说,如果只启动一次服务,第一次启动时,startId1 ,那么执行 stopSelf(startId) 时的 startId 也为 1 ,则销毁成功。如果启动了两次服务,假设第二次启动时 startId2 ,当处理第一次的逻辑时执行到stopSelf(startId) ,此时的 startId 为上一次的 startId,即为 1 ,则销毁不成功,继续处理第二次的处理逻辑,处理完才会销毁成功。也就是说,多次启动服务时,会顺序处理每次的请求,全部处理完后,才销毁服务

  5. onDestroy() 中会退出循环,即销毁线程,回收资源。

IntentService 使用示例

自定义 IntentService 类:

public class TestIntentService extends IntentService {

    private static final String PARAM = "test";

    public TestIntentService() {
        super("TestIntentService");
    }

    public static void startIntentService(Context activity, String param) {
        Intent intent = new Intent(activity, TestIntentService.class);
        intent.putExtra(PARAM, param);
        activity.startService(intent);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("TestIntentService", "onHandleIntent 线程名称" + Thread.currentThread().getName());

        if (intent.getStringExtra(PARAM).equals("first")) {
            try {
                Log.d("TestIntentService", "first start");
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            try {
                Log.d("TestIntentService", "again start");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("TestIntentService", "onDestroy 线程名称" + Thread.currentThread().getName());
    }
}

启动服务:

if (isReadStart) {
               TestIntentService.startIntentService(this, "again");
           } else {
               TestIntentService.startIntentService(this, "first");
               isReadStart = true;
           }

打印日志:

D/TestIntentService: onHandleIntent 线程名称 IntentService[TestIntentService]
D/TestIntentService: first start
D/TestIntentService: onHandleIntent 线程名称 IntentService[TestIntentService]
D/TestIntentService: again start
D/TestIntentService: onDestroy 线程名称 main