AsyncTaskでバックグラウンド処理を行う の変更点

データベース問い合わせ等の比較的重たい処理を、UI threadに負荷を与えずに行いたい場合、AsyncTaskクラスを利用します。
AsyncTaskクラスは別スレッドでのバックグラウンド処理と、処理前と処理後のUI threadへのコールバックの2つを併せ持つ、便利なクラスです。
AsyncTaskクラスは別スレッドでのバックグラウンド処理と、処理前と処理後のUI threadへのコールバックの2つを提供してくれる、便利なクラスです。
AsyncTaskを利用するには、AsyncTaskのサブクラスを実装する必要があります。
#BR
サンプルとして、GeoCoderを使った簡易住所検索アプリを作成しながら、AsyncTaskの使用方法を解説します。
#BR
** Activityの作成 [#g81d78a9]

新規Androidプロジェクトを作成し、タスク実行を行うAddressRequestActivityを作成します。
AddressRequestActivityでは、Button押下時にEditTextに入力された文字列を元にAddressを取得しTextViewに表示をします。
#BR
&REF(address_request.xml);
&REF(AddressRequestActivity.java);
#BR
** Taskの実装 [#jcd864ec]
「Address取得→データの整形→表示」までの処理を、AddressRequestTaskクラスを作成し、実装します。
#BR
&REF(AddressRequestTask.java);
#BR
AsyncTaskのサブクラスでは、実行時引数(Param)、進捗単位(Progress)、処理結果(Result)で扱う型を指定する必要があります。
AddressRequestTaskの場合は、実行時引数(String)、進捗単位(Integer)、処理結果(Address)を扱います。
 public class AddressRequestTask extends AsyncTask<String, Integer, Address>
#BR

doInBackground()を実装し、必要に応じてonPreExecute()やonPostExecute()を実装します。
 @Override
 protected void onPreExecute() { // …①
     mResultText.setText(null);
     mProgressDialog = new ProgressDialog(mActivity);
     mProgressDialog.setTitle("In Processing...");
     mProgressDialog.setIndeterminate(true);
     mProgressDialog.show();
 }
 
 @Override
 protected Address doInBackground(String... locationNames) { // …②
     Address result = null;
     try {
         List<Address> results = mGeocoder.getFromLocationName(locationNames[0], 1);
         if (results != null && !results.isEmpty()) {
             result = results.get(0);
         }
     } catch (IOException e) {
         Log.e(TAG, e.getMessage());
     }
     return result;
 }
 
 @Override
 protected void onPostExecute(Address result) { // …③
     mProgressDialog.dismiss();
     
     if (result != null) {
         double latitude = result.getLatitude();
         double longitude = result.getLongitude();
         StringBuilder builder = new StringBuilder();
         builder.append("latitude:").append(String.valueOf(latitude)).append("\n");
         builder.append("longitude:").append(String.valueOf(longitude));
         mResultText.setText(builder.toString());
     } else {
         Toast toast = Toast.makeText(mActivity, "Not Found.", Toast.LENGTH_LONG);
         toast.show();
     }
 }
#BR

AddressRequestTaskでは
①onPreExecute()で進捗ダイアログの表示を行い、
②doInBackground()でGeoCoderへの問い合わせ→Address取得、
③onPostExecute()でデータの整形→表示と、進捗ダイアログの非表示を行っています。
#BR
doInBackground()内でUI threadに関わる処理を記述すると、実行時にエラーとなるので注意が必要です。
ダイアログの表示/非表示や取得データの表示といった、画面の描画を伴うような処理はdoInBackground()に記述せずに、
onPreExecute()やonPostExecute()に記述する必要があります。
#BR
タスクを実行するにはexecute()メソッドを呼びます。
AddressRequestActivityのボタン押下時に、入力値の取得とタスクの実行を実装しています。
 String locationName = mLocationNameEdit.getText().toString();
 AddressRequestTask task = new AddressRequestTask(this);
 task.execute(locationName);

#BR

** 進捗ダイアログの更新 [#z65bfb61]
サンプルのProgressDialogにはsetIndeterminate()にtrueを設定し無限に表示を続けるよう指定していますが、
doInBackground()内での処理の進み具合に応じてダイアログを更新したい場合、publishProgress()メソッドを使います。
#BR
publishProgress()はAsyncTaskの実行時同様、コールバックを自分自身に設定したMessageをHandlerへPostし、
バックグラウンド処理からダイアログを更新するUI threadへのアクセスを実現しています。
publishProgress()への引数は、進捗単位(Progress)に指定した型を用います。
 Integer progress = 10;
 publishProgress(progress);
#BR

publishProgress()メソッドが処理されると、そのコールバックとしてonProgressUpdate()メソッドが呼ばれます。
引数の値は、publishProgress()で指定した値が入ります。
 @Override
 protected void onProgressUpdate(Integer... progress) {
     mProgressDialog.setProgress(progress[0]);
 }
#BR
#BR
----
#comment(below,noname)