Androidアプリケーションに応答性を維持する:AsyncTask

7912 ワード

長時間かかる可能性のある操作は、UIのメインスレッドに置くのではなく、ワークスレッドを作成して処理する必要があります.現在の局Activityが5秒以内にユーザーにイベントをクリックしていないか、BroadcastReceiverがブロードキャストを受信してから10秒以内に戻ってこないと、Androidはアプリケーションの応答なし(ANR)のダイアログボックスを投げ出して、ユーザーがアプリケーションを閉じるかどうかを選択します.
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