前言
经历过面试的人应该都知道,一般我们在进行技术面试的时候,面试官都会问你,在项目开发中遇到过什么棘手的问题?最后是怎么解决的?本人之前就问到过好几次,可是由于准备不足,一时之间想不起来所遇到过的“棘手”问题,所以好几次都没能很好地回答这个问题。因此,在这里记录下本人在接下来工作中遇到的棘手问题以及最后解决方案。
1. 通过SharePerference初始化数据(数据量比较大)时,造成ANR(Application Not Response)
问题描述:
第一次启动应用,考虑到初始化的数据量过多,直接在UI线程里操作可能会阻塞UI线程造成ANR,所以使用了异步方式(线程)完成数据初始化操作,然后通过Handler通知主线程继续往下运行,然而实际运行时还是造成了ANR,经调试结合debug信息发现,初始化早已完成,但主线程却没有接收到Handler发出的完成信息继续往下执行,如果没有其他原因,即使他在主线程中执行完成它也不应该也不足以导致ANR,然而实际却出现了。
PS:打断点debug时又正常了(╬◣д◢)
解决方案
通查看ANR的trace日志,终于找到了发生ANR的地方
可以看到是卡在了QueueWork.waitToFinish,该函数的等待导致发生了ANR
看日志中描述的waitToFinish()方法:
/**
* Trigger queued work to be processed immediately. The queued work is processed on a separate
* thread asynchronous. While doing that run and process all finishers on this thread. The
* finishers can be implemented in a way to check weather the queued work is finished.
*
* Is called from the Activity base class's onPause(), after BroadcastReceiver's onReceive,
* after Service command handling, etc. (so async work is never lost)
*/
public static void waitToFinish() {
...
}
看上面方法解释:当Activity调用onPause()方法,或者BroadcastReceiver调用onReceive()方法的时候会调用该方法,这样就能保证异步任务不会丢失。
在结合调用的apply方法,找到对应代码出问题地方
public void apply() {
final long startTime = System.currentTimeMillis();
final MemoryCommitResult mcr = commitToMemory();
final Runnable awaitCommit = new Runnable() {
public void run() {
try {
mcr.writtenToDiskLatch.await();
} catch (InterruptedException ignored) {
}
if (DEBUG && mcr.wasWritten) {
Log.d(TAG, mFile.getName() + ":" + mcr.memoryStateGeneration