Android開(kāi)發(fā)中難免碰到ANR問(wèn)題茸塞,但是網(wǎng)上關(guān)于ANR的文章并不多,那我就寫(xiě)一篇最近工作中碰到ANR的分析過(guò)程备畦。
分析過(guò)程
- 先查一下網(wǎng)上關(guān)于ANR方面的文章计盒,找到的大部分都是說(shuō)不要主線程執(zhí)行耗時(shí)操作,但是我本來(lái)就在子線程里執(zhí)行的下載操作的藏杖。怎么會(huì)產(chǎn)生ANR?
- 接著去分析 /data/anr/traces.txt, 好家伙data文件夾不是要root權(quán)限 才能訪問(wèn)嗎将塑?怎么辦不是要我root吧,然后我又去查了資料發(fā)現(xiàn)可以用下面的命令導(dǎo)出traces文件
adb shell cat /data/anr/traces.txt > e:\anr.txt
- 打開(kāi)anr.txt 有1000多行看著都暈蝌麸,沒(méi)辦法慢慢看吧点寥,看到SharedPreferences想到了我不是在下載的時(shí)候存了下載的進(jìn)度了,猜想應(yīng)該是它出的問(wèn)題
| group="main" sCount=1 dsCount=0 obj=0x12dbdac0 self=0xb4256800
| sysTid=4302 nice=0 cgrp=default sched=0/0 handle=0x9d207000
| state=S schedstat=( 11836166912 2318327808 16610 ) utm=552 stm=631 core=1 HZ=100
| stack=0x9c7f2000-0x9c7f4000 stackSize=1036KB
| held mutexes=
at libcore.io.Posix.fsync(Native method)
at libcore.io.BlockGuardOs.fsync(BlockGuardOs.java:143)
at java.io.FileDescriptor.sync(FileDescriptor.java:74)
at android.os.FileUtils.sync(FileUtils.java:152)
at android.app.SharedPreferencesImpl.writeToFile(SharedPreferencesImpl.java:598)
at android.app.SharedPreferencesImpl.access$800(SharedPreferencesImpl.java:51)
at android.app.SharedPreferencesImpl$2.run(SharedPreferencesImpl.java:512)
- locked <@addr=0x131d6bf0> (a java.lang.Object)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
然后去代碼里查了一下寫(xiě)的apply 方法来吩,再去網(wǎng)上查了一下apply敢辩、和commit的區(qū)別
SharedPreferencesImpl源碼分析
原來(lái)的apply方法是異步執(zhí)行的,因?yàn)橄螺d很快 有進(jìn)行一次寫(xiě)入操作,在異步寫(xiě)入時(shí)導(dǎo)致死鎖弟疆。
commit是同步的阻塞的戚长。那就把a(bǔ)pply改成commit試一下,果然ok了怠苔。
TIP
在分析traces.txt首先搜索自己項(xiàng)目包名的堆棧历葛,這樣能很快定位問(wèn)題,如果沒(méi)有那就要一步一步的看嘀略,在關(guān)聯(lián)自己的代碼進(jìn)行聯(lián)想恤溶。應(yīng)該能解決ANR問(wèn)題。