android時間のかかるタスク_ANR


ANR
一部のアプリケーションでは、アプリケーションの応答なしダイアログ(ANR:Application Not Responding)と呼ばれるダイアログボックスが使用中にポップアップされます.このプロンプトボックスには、アプリケーションの待機と停止の2つの選択肢がありますが、そのポップアップはユーザーが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でサービスを開始し、サービスでスレッドを起動して時間のかかるタスクを処理することをお勧めします.