Question:最近在项目中出现了偶现的bug,打开详情页面会白屏,只要出现了一次白屏,退出在打开别的文章详情页都是白屏的状态。
解决问题:Android项目中只要可以复现的bug基本上都能通过打断点进行解决(吹个🐂皮)。可是这个问题是偶现的而且机率极小,于是开始排查问题。
怀疑的问题点:
- 加载文章内容的接口出了问题
对出现bug的手机进行抓包,发现加载文章内容的接口没有任何问题 - 加载内容的时候内容已经加载完成,但是没有显示出来
进过排查设置view可见与不可见的地方没有任何问题。 - 顺理成章的怀疑用webview加载内容的时候,内容根本就没有处理好
最后才发现请求完文章内容接口之后,为了达到详情页秒开的目的,将文章页的html内容在本地进行了组装。这个组装的过程是个异步处理的过程,好死不死的用到了AsyncTask,最后也就是这个地方出现了问题
AsyncTask就是Google官方提供的一个异步线程处理,ui线程更新的很好的handler+thread的封装类,方便开发者使用起来比较方便,具体的使用方式自行Google。我现在想说的是Asynctask串行和并行的问题。
在执行Asynctask任务的时候,系统提供了两个运行方式。
htmlParserTaskTask.execute();
htmlParserTaskTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
在介绍这两个方法的差异之前,先说明两个AsyncTask里面的Executor
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
//上一个任务执行完才能去执行下一个任务串行执行
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
public static final Executor THREAD_POOL_EXECUTOR;
static {
//线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
- execute()
当你通过这个方式去执行任务的时候,默认的任务执行器就是SerialExecutor,串行执行任务,one by one。
-executeOnExecutor()
当你通过这个方式去执行任务的时候,这个时候是并行执行任务的。使用的任务执行器就是线程池了。
了解这些基本知识之后,去解决问题
问题的点在与这个Asynctask没有执行,你点开的文章的处理内容的Asynctask没有执行。因为是串行的执行任务。有的人会说将里面执行的方式改为并行不就行了吗,我现在只能告诉你是不行的,这个方式用起来还是有一定的风险,并不能保证百分百的去触发。所以在项目中我把AsyncTask进行废弃了,项目中采用的是Rxjava+Retrofit+MVP,于是我采用了Rxjava进行处理,之后就没有任务白屏的出现。
Asyncatask有的时候比较坑,能不用就不用这个玩意吧,还说一句题外话,AsyncTask和极光推送有冲突