位于包 :
androidx.arch.core.executor
++++TaskExecutor
++++ArchTaskExecutor
++++DefaultTaskExecutor
复习 Jetpack
时发现了 androidx.arch.core.executor
包中有一个线程池实现类 ArchTaskExecutor
,内部实现了切换到主线程的功能。
使用的方式十分顺滑:
//切换到主线程
ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable{
});
//子线程执行
ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable{
});
复制代码
先看 ArchTaskExecutor
暴露的方法:
- executeOnDiskIO(Runnable runnable)
- postToMainThread(Runnable runnable)
- Executor getMainThreadExecutor()
- Executor getIOThreadExecutor()
- boolean isMainThread()
- void setDelegate(TaskExecutor taskExecutor)
分析具体的方法之前看下 ArchTaskExecutor
类的构造方式:
ArchTaskExecutor 继承自抽象类 TaskExecutor ,TaskExecutor 很简单,只有4个方法,其中可以看到方法executeOnMainThread(Runnable runnable) 中的逻辑是如果任务不是在主线程上,那么将调用 postToMainThread(runnable) 将任务切换至主线程中执行。
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();
}
复制代码
接着看 ArchTaskExecutor
,ArchTaskExecutor
实现了一个单例提供访问实例入口:
public class ArchTaskExecutor extends TaskExecutor {
private static volatile ArchTaskExecutor sInstance;
private TaskExecutor mDelegate;
private TaskExecutor mDefaultTaskExecutor;
...
@NonNull
public static ArchTaskExecutor getInstance() {
if (sInstance != null) {
return sInstance;
}
synchronized (ArchTaskExecutor.class) {
if (sInstance == null) {
sInstance = new ArchTaskExecutor();
}
}
return sInstance;
}
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
}
复制代码
从源码中还发现有 mDelegate
和 mDefaultTaskExecutor
,其中 mDelegate
是 ArchTaskExecutor
实现的代理类,承担功能的具体实现。mDefaultTaskExecutor
是已实现的默认线程池代理类,mDelegate
默认被赋予 mDefaultTaskExecutor
的实例,同时支持外部自定义实现线程池。
public class ArchTaskExecutor extends TaskExecutor {
...
//设置自定义的线程池
public void setDelegate(@Nullable TaskExecutor taskExecutor) {
mDelegate = taskExecutor == null ? mDefaultTaskExecutor : taskExecutor;
}
}
复制代码
再看下一开始讲到的 ArchTaskExecutor
中暴露的方法实现:
public class ArchTaskExecutor extends TaskExecutor {
...
//提供主线程的对象获取
@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);
}
};
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();
}
}
复制代码
以上的几个方法都是直接由代理类直接实现。
那么,接下来再看看代理类 DefaultTaskExecutor
的实现。
同样的,DefaultTaskExecutor 也是继承抽象类 TaskExecutor,然后实现了父类的抽象方法,DefaultTaskExecutor 完整源码如下
public class DefaultTaskExecutor extends TaskExecutor {
private final Object mLock = new Object();
private final ExecutorService mDiskIO = Executors.newFixedThreadPool(2, new ThreadFactory() {
private static final String THREAD_NAME_STEM = "arch_disk_io_%d";
private final AtomicInteger mThreadId = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName(String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement()));
return t;
}
});
@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();
}
}
复制代码
经过上边分析:
DefaultTaskExecutor
继承TaskExecutor
,并实现了父类方法- 内部实现了线程池 Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory),所以
ArchTaskExecutor
实际上是对Executors
的一层包装。 - 实现了
Handler
,将任务切换至主线程。
总结:
ArchTaskExecutor
使用代理模式实现了一个内部的线程池 DefaultTaskExecutor
提供使用,同时支持切换主线程的功能。其中如果使用者没有设置自己的 TaskExecutor
,那么 ArchTaskExecutor
将会使用 DefaultTaskExecutor
作为默认实现的线程池。
后面如果需要用到线程池的地方,就不用再自己写一堆实现方法了,直接调用 ArchTaskExecutor
就行了,如果不满足要求,就自己再定义一个 TaskExecutor
。