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


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