ANR(Application Not Responding)定義
在Android上,如果你的應用程序有一段時間響應不夠靈敏,系統會向用戶顯示一個對話框,這個對話框稱作應用程序無響應(ANR:Application Not Responding)對話框。用戶可以選擇“等待”而讓程序繼續運行,也可以選擇“強制關閉”。所以一個流暢的合理的應用程序中不能出現anr,而讓用戶每次都要處理這個對話框。因此,在程序裏對響應性能的設計很重要,這樣系統不會顯示ANR給用戶。默認情況下,在android中Activity的最長執行時間是5秒,BroadcastReceiver的最長執行時間則是10秒。
ANR的避免方案:將耗時任務放入work thread。但在某些情況下,我們需要及時得到workthread的返回結果進行下一步的操作,這種情況下該怎麼辦呢?這裏提供兩種解決方案:
1、使用Callable 和 Future進行超時處理:demo如下
<pre name="code" class="java">private boolean checkNewCellProvider(){
boolean newCellInfoFlag = false;
if(Build.VERSION.SDK_INT>=17){
ExecutorService exec = Executors.newFixedThreadPool(1);
Callable<Boolean> call = new Callable<Boolean>() {
public Boolean call() throws Exception {
//開始執行耗時操作
CellInfo cellInfo = Cells.getCellInfoQuietly(mAppContext);
if(cellInfo != null)
return true;
else {
LogUtil.e(TAG, "SDK="+Build.VERSION.SDK_INT+"but get no cell");
return false;
}
}
};
try {
Future<Boolean> future = exec.submit(call);
newCellInfoFlag = future.get(500, TimeUnit.MILLISECONDS); //任務處理超時時間設爲500毫秒
} catch (TimeoutException ex) {
newCellInfoFlag = false;
} catch (Exception e) {
newCellInfoFlag = false;
} finally{
// 關閉線程池
exec.shutdown();
}
}
return newCellInfoFlag;
}
<pre name="code" class="java">方案2:使用Countdownlatch
CountDownLatch latch = ExceptionReporter.postSingleError(AppContext.getInstance(mContext),ExceptionReporter.LOG_URL, error, mLocalPath + "/"+ filename);
try{
latch.await(500, TimeUnit.MILLISECONDS);
}catch (InterruptedException e1) {
e1.printStackTrace();
}
public synchronized static CountDownLatch postSingleError(
final AppContext context, final String url, final String data,
final String filepath) {
final CountDownLatch latch = new CountDownLatch(1);
new Thread() {
public void run() {
if (!sIsSending) {
sIsSending = true;
if (DEBUG) LogUtil.i(TAG, "start uploading error log");
processOldLogs(context, url,new File(filepath).getParentFile());
try {
String result = context.postSync(url, data.getBytes());
if (DEBUG) LogUtil.i(TAG, result);
} catch (Exception e) {
}
}
sIsSending = false;
latch.countDown();
}
}.start();
return latch;
}