Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android處理耗時任務_ANR

android處理耗時任務_ANR

編輯:關於Android編程


ANR

有些應用在使用中會彈出一個對話框,一般這個對話框叫做應用程序無響應對話框(ANR:Application Not Responding)。雖然這個提示框有等待和關閉應用程序兩種選擇,但是它的彈出就已經影響了用戶使用app過程中的體驗,所以一般來說,Android開發的過程中都會嚴格控制ANR的出現。

ANR表面原因:應用在一定時間內(一般是5秒)沒有響應輸入操作(例如輸入,按鈕,手勢觸摸等)。

ANR根本原因:Android主線程中進行耗時操作,造成主線程阻塞;BroadcastReceiver生命周期結束前沒有完成相應的耗時任務。
Android應用都是運行在主線程中的,包括activity、service的生命周期,ui的刷新(所以主線程又叫ui線程),輸入響應操作等等。也就是說任何在主線程中運行的函數都不能進行耗時的動作,否則會阻塞主線程,導致輸入無法響應,從而彈出ANR。
BroadcastReceiver的生命周期很短(一般為10秒),如果在它生命周期結束前耗時任務沒有完成,Android認為該程序沒有響應。

這些耗時的操主要包括網絡,數據庫,大量的計算操作(如bitmap的處理)等。

簡單的解決方案

1、為了防止主線程被阻塞,通常需要啟動子線程來處理耗時任務,子線程的任務完成時通過handler通知主線程,讓主線程刷新ui等。下面是一個簡單的事例:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

	private TextView text;
	private Button button;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		text = (TextView) findViewById(R.id.text);
		button = (Button) findViewById(R.id.button);

		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				System.out.println("-->開啟子線程");
				new TaskThread().start();
			}
		});

	}

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
			{
				System.out.println("-->回到主線程刷新ui任務");
				text.setText("任務完成");
			}
				break;

			default:
				break;
			}
		};
	};

	class TaskThread extends Thread {
		public void run() {
			System.out.println("-->做一些耗時的任務");
			try {
				sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			handler.sendEmptyMessage(0);
		};
	};
}
運行後打印結果如下:
05-26 05:30:16.490: I/System.out(381): -->開啟子線程
05-26 05:30:16.510: I/System.out(381): -->做一些耗時的任務
05-26 05:30:17.011: I/System.out(381): -->回到主線程刷新ui任務

2、BroadcastReceiver的函數也是由主線程調用的,但是不應該啟動子線程來處理耗時任務。因為BroadcastReceiver屬於一個空進程,在BroadcastReceiver有限的生命周期結束後他的優先級就會降低,系統很容易就把它回收了,這樣,子線程的宿主已經被回收了,那麼它的子線程也會被殺死。所以建議在BroadcastReceiver中啟動service,在service中啟動線程處理耗時任務。





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved