android應用程序中對於ANR主線程超時不響應導致強制關閉的解決方案

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章