个人关于使用IntentService的思考

来源:互联网 发布:淘宝贷款多久放款 编辑:程序博客网 时间:2024/06/09 22:18

最近要做个多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后继续执行。

原创粉丝点击