万丈架构平地起,带你拆解Google Android Architecture Component(以下简称 Arch)系列之一。
此次解析比较简约且独立的部分,android.arch.core.executor包。让我们来学习下Google的TaskExecutor。
此包从属于android.arch.core:runtime 可以理解为acrh的基础工具集。
包下就三个类:
1.TaskExecutor
抽象类,基类,如下:
public abstract class TaskExecutor {
public abstract void executeOnDiskIO(@NonNull Runnable runnable);
public abstract void postToMainThread(@NonNull Runnable runnable);
public void executeOnMainThread(@NonNull Runnable runnable) {
if (isMainThread()) {
runnable.run();
} else {
postToMainThread(runnable);
}
}
public abstract boolean isMainThread();
}
提供四个方法,定义TaskExecutor的功能,即在主线程/IO线程执行任务。executeOnMainThread方法判定是否此方法执行是否已在主线程,如果在则直接执行,不在则post只主线程。
2.ArchTaskExecutor
继承自TaskExecutor 如下:
public class ArchTaskExecutor extends TaskExecutor {
private static volatile ArchTaskExecutor sInstance;
@NonNull
private TaskExecutor mDelegate;
@NonNull
private TaskExecutor mDefaultTaskExecutor;
@NonNull
private static final Executor sMainThreadExecutor = new Executor() {
@Override
public void execute(Runnable command) {
getInstance().postToMainThread(command);
}
};
@NonNull
private static final Executor sIOThreadExecutor = new Executor() {
@Override
public void execute(Runnable command) {
getInstance().executeOnDiskIO(command);
}
};
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
public static ArchTaskExecutor getInstance() {
if (sInstance != null) {
return sInstance;
}
synchronized (ArchTaskExecutor.class) {
if (sInstance == null) {
sInstance = new ArchTaskExecutor();
}
}
return sInstance;
}
public void setDelegate(@Nullable TaskExecutor taskExecutor) {
mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor;
}
@Override
public void executeOnDiskIO(Runnable runnable) {
mDelegate.executeOnDiskIO(runnable);
}
@Override
public void postToMainThread(Runnable runnable) {
mDelegate.postToMainThread(runnable);
}
@NonNull
public static Executor getMainThreadExecutor() {
return sMainThreadExecutor;
}
@NonNull
public static Executor getIOThreadExecutor() {
return sIOThreadExecutor;
}
@Override
public boolean isMainThread() {
return mDelegate.isMainThread();
}
}
实现了3个抽象方法,这里使用代理模式,实现后,执行全部转交给mDelegate,而此类也提供setDelegate的方法,允许client从外部提供一个TaskExecutor,这样设计的好处:
1.通过代理,实际的执行模型(如:DefaultTaskExecutor的ExecutorService)交给代理类实现,隐藏了实现细节。
2.给client比较高的自由度,客户端可以定义自己的TaskExecutor,从而定义实际的执行模型及队列等,也有利于方法埋点等操作。
另外,通过getMainThreadExecutor与getMainThreadExecutor两个静态方法将sMainThreadExecutor与sIOThreadExecutor暴露给外部,而sMainThreadExecutor与sIOThreadExecutor相当于一个适配器,将ArchTaskExecutor的任务执行转换成标准的Executor,并未暴露mDelegate中的ExecutorService。
3.DefaultTaskExecutor
也继承自TaskExecutor,如下:
public class DefaultTaskExecutor extends TaskExecutor {
private final Object mLock = new Object();
private ExecutorService mDiskIO = Executors.newFixedThreadPool(2);
@Nullable
private volatile Handler mMainHandler;
@Override
public void executeOnDiskIO(Runnable runnable) {
mDiskIO.execute(runnable);
}
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
@Override
public boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
}
ArchTaskExecutor的默认代理类,当client没有手动设置delegate时,使用其执行任务。
使用了newFixedThreadPool的线程池模型。 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。源码设定最大并发数是2。
postToMainThread时,mMainHandler初始化使用了双重效验锁。
总结:
1.整个包非常独立,如果你自己想实现一个Task Executor,完全可以仿照实现,并丰富功能。