Androidアプリケーションに応答性を維持する:AsyncTask
7912 ワード
長時間かかる可能性のある操作は、UIのメインスレッドに置くのではなく、ワークスレッドを作成して処理する必要があります.現在の局Activityが5秒以内にユーザーにイベントをクリックしていないか、BroadcastReceiverがブロードキャストを受信してから10秒以内に戻ってこないと、Androidはアプリケーションの応答なし(ANR)のダイアログボックスを投げ出して、ユーザーがアプリケーションを閉じるかどうかを選択します.
ANRを避けるにはどうすればいいですか?
長時間の操作を処理するワークスレッドを作成する最も効率的な方法は、AsyncTaskクラスを継承することです.
一方、UIマスタースレッドは、非同期ワークスレッドインスタンスを簡単に作成し、execute()メソッドを呼び出すだけでよい.
より複雑なインタラクションが必要な場合は、ThreadクラスまたはHandlerThreadクラスを継承できます.この場合、カスタム作業スレッドで呼び出す必要があります.
をクリックして、作業スレッドの優先度を下げます.新しいスレッドのデフォルトの優先度はUIマスタースレッドと同じであるため、この設定をしないとアプリケーションの応答速度が遅くなります.さらに、UIマスタースレッドは、ジョブスレッドにタスクの完了状況を返信するHandlerを提供する必要があります.BroadcastReceiverで長時間の操作が必要な場合はIntentServiceクラスを使用します.さらに、StrictModeクラスを使用して、UIマスタースレッドまたは他のコンポーネントにおける長時間の動作を監視することができる.
StrictModeでは、JNIのハードディスク(HDD)やネットワークアクセスなど、すべての問題がトリガーされるとは限らないことに注意してください.
参考資料:
Android > Develop > Training > Keeping Your App Responsive https://developer.android.com/intl/zh-cn/training/articles/perf-anr.html
Android > Develop > Reference > AsyncTask https://developer.android.com/reference/android/os/AsyncTask.html
ANRを避けるにはどうすればいいですか?
長時間の操作を処理するワークスレッドを作成する最も効率的な方法は、AsyncTaskクラスを継承することです.
// :AsyncTask ( ) 。
// , java.util.concurrent
// Executor、ThreadPoolExecutor FutureTask。
// AsyncTask<Params, Progress, Result>
// 、 、 。 , Void 。
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// AsyncTask ,
// , Override。
// : UI 。
@Override
protected void onPreExecute() {
// UI,
}
// : 。
// UI execute(Params...) ( ),
// 。
// publishProgress(Progress...) UI ,
// 。
@Override
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
// UI
publishProgress((int) ((i / (float) count) * 100));
// UI cancel(false) ,
if (isCancelled()) break;
}
return totalSize;
}
// : publishProgress(Progress...) UI 。
@Override
protected void onProgressUpdate(Integer... progress) {
//
}
// : ( ) UI 。
// : , ,
// onCancelled(Result) 。
@Override
protected void onPostExecute(Long result) {
//
showDialog("Downloaded " + result + " bytes");
}
// , , UI 。
@Override
protected void onCancelled(Long result) {
//
}
}
一方、UIマスタースレッドは、非同期ワークスレッドインスタンスを簡単に作成し、execute()メソッドを呼び出すだけでよい.
// 。
// :AsyncTask UI 。
DownloadFilesTask downloadFilesTask = new DownloadFilesTask();
// : UI ,
// , 。
// , AsyncTask 。
// , Android 1.6(API 4) ,execute 。
// Android 3.0(API 11) ,execute ,
// ,
//(AsyncTask ) 。
// ( doInBackground ),
// , :
// downloadFilesTask.executeOnExecutor(AsyncTask.
// THREAD_POOL_EXECUTOR, url1, url2, url3);
downloadFilesTask.execute(url1, url2, url3);
// 。
// true , false
//(false isCancelled() )。
downloadFilesTask.cancel(false);
より複雑なインタラクションが必要な場合は、ThreadクラスまたはHandlerThreadクラスを継承できます.この場合、カスタム作業スレッドで呼び出す必要があります.
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
をクリックして、作業スレッドの優先度を下げます.新しいスレッドのデフォルトの優先度はUIマスタースレッドと同じであるため、この設定をしないとアプリケーションの応答速度が遅くなります.さらに、UIマスタースレッドは、ジョブスレッドにタスクの完了状況を返信するHandlerを提供する必要があります.BroadcastReceiverで長時間の操作が必要な場合はIntentServiceクラスを使用します.さらに、StrictModeクラスを使用して、UIマスタースレッドまたは他のコンポーネントにおける長時間の動作を監視することができる.
public void onCreate() {
// ,
if (DEVELOPER_MODE) {
//
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
// All CustomSlowCalls、DiskReads、DiskWrites、
// Network、ResourceMismatches
.detectAll()
// log
.penaltyLog()
// ThreadPolicy
.build());
//
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
// All ActivityLeaks、CleartextNetwork、
// FileUriExposure、LeakedClosableObjects、
// LeakedRegistrationObjects、LeakedSqlLiteObjects
.detectAll()
// log
.penaltyLog()
// VmPolicy
.build());
}
super.onCreate();
}
StrictModeでは、JNIのハードディスク(HDD)やネットワークアクセスなど、すべての問題がトリガーされるとは限らないことに注意してください.
参考資料:
Android > Develop > Training > Keeping Your App Responsive https://developer.android.com/intl/zh-cn/training/articles/perf-anr.html
Android > Develop > Reference > AsyncTask https://developer.android.com/reference/android/os/AsyncTask.html