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