个人关于使用IntentService的思考

最近要做个多app module 位于一个Project 下的 启动优化,创建公用的IntentService到各自的Application中差异化实现细节。不想使用静态的Application实例作为回调对象传入,因此有了以下伪代码。

package com.personalcenter.service;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.support.annotation.Nullable;
import android.util.Log;

import com.personalcenter.util.ProguardUtil;

import java.util.concurrent.CountDownLatch;

/**
 * app 启动优化 后台执行任务回调由外界决定执行任务内容
 * Created by dhs on 17/12/23
 */

public class InitIntentService extends IntentService {
    private Listener mListener;
    public static final String APP_INIT_ACTION = "app_init_action";
    private final CountDownLatch mLatch;


    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public InitIntentService() {
        super(InitIntentService.class.getCanonicalName());
        Log.e("InitIntentService", "InitIntentService(InitIntentService.java:31)" + this);
        mLatch = new CountDownLatch(1);
    }

    public static InitIntentService startBackService(Context context) {
        Intent intent = new Intent(context, InitIntentService.class);
        intent.setAction(APP_INIT_ACTION); // 可通过该action来分类处理任务
        context.startService(intent);
       return new InitIntentService();
   }

   public void setHandleBackListener(Listener listener) {
       Log.e("InitIntentService", "setHandleBackListener(InitIntentService.java:41)" + Thread.currentThread() + "service-->>" + this);
       mLatch.countDown();
       mListener = listener;
   }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //do background init
        try {
            Log.e("InitIntentService", "onHandleIntent(InitIntentService.java:51)" + Thread.currentThread() +"service-->>"+ this);
            mLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ProguardUtil.checkNotNull(mListener, "Listener should not be null at first init...");
        mListener.doBackgroundInit();
    }

    public interface Listener {
        void doBackgroundInit();
    }

    @Override
    public void onCreate() {
        Log.e("InitIntentService", "onCreate(InitIntentService.java:68)-->>" + this);
        super.onCreate();
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        Log.e("InitIntentService", "onStartCommand(InitIntentService.java:73)-->>" + this);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e("InitIntentService", "onDestroy(InitIntentService.java:80)-->>" + this);
        super.onDestroy();
    }
}

上述代码为本人新建IntentService 的伪尝试代码,尝试外界静态方法调用创建service,并通过service对象传递接口回调对象

问题:
1. Service 的创建是交给系统的,不同于Fragment这种类view形式,所以new 构造创建Service会在start 基础上额外创建一个Service对象。
且通过new 构造创建的Service不会走Service的生命周期方法。
2. 通过以下方式完成创建和接口回调对象的传递:

InitIntentService.startBackService(this).setHandleBackListener(this);

IntentService的原理是通过HandlerThread来实现子线程在后台处理任务,而HandlerThread则是在Thread的基础上添加Looper构建子线程处理任务的环境。
通过上述方法将app 实例传到的对象非最终走系统回调的IntentService对象。
3. 系统在创建出IntentService实例后[系统调用对应构造函数创建],调用Service生命周期函数 onCreate和onStartCommand,
在IntentService源码中:

...
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

在onStartCommand 中调用onStart方法:

...
mServiceHandler.sendMessage(msg);
...

在ServiceHandler中处理:

 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);
        }
    }

最终Handler所post的内容会在Handler所绑定的looper线程中的MessageQueue中dispatch,即 onHandleIntent在IntentService里的
handlerThread所创建的Thread中执行。
4.基于上述分析,两个IntentService的创建后,通过new 构建的Service对象持有了app实例,而系统创建的Service并没有调用传递回调对象的方法 setHandleBackListener,而且只有系统创建的Service才会走生命周期方法,那么在onHandleIntent
回调中,传入的回调对象必定为null,调用多线程锁对象
mLatch.await(); 则会让子线程一直等待,因为系统创建的Service没有调用传入回调对象的方法,也就不会 执行 mLatch.countDown(); onHandleIntent 后续的代码也就不会执行!

另:CountDownLatch 是用于多线程间控制执行流程的位于java 并发包下的同步辅助类,允许一个或多个类挂起(await),在调用countdown后继续执行。

你可能感兴趣的:(四大组件,android)