fc2ブログ

戌印-INUJIRUSHI- (Androidあれこれ)

Androidのプログラミングをメインにしてます。記事に貼られたソースコードはダブルクリックすることで行番号をはずしてコピーすることができます。

 
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
10

非同期処理:AsyncTaskLoader

AsyncTaskLoader は Android で用意された非同期処理に特化したスレッドクラスです。



AsyncTaskLoader クラスは Android 3.0 (API 11) から追加された Loader クラスのサブクラスで、以前「非同期処理:AsyncTask」で紹介した AsyncTask を内包しています。

Android 3.0 で追加されていますが Android Support Library に含まれているため、Android 3.0 以前でも利用できます。
Android Support Library の場合、Loader を実行するために必要な getSupportLoaderManager が FragmentActivity に実装されているため、呼び出し元のアクティビティは FragmentActivity を継承する必要があります。

AsyncTaskLoader と AsyncTask の違いは UI 処理をどこで行うかにあります。
AsyncTask では非同期処理の実行前後の UI 処理は AsyncTask クラス内に定義していましたが
AsyncTaskLoader では LoaderCallbacks インターフェイスを介して行われるため、非同期処理の実行前後の UI 処理も Activity 内に定義できるようになりました。
これにより UI 処理は Activity 側、非同期処理は AsyncTaskLoader 側と住み分けができるようになっています。
android_AsyncTaskLoader.png


■ ソースコードで定義
次のサンプルコードでは Android Support Library の AsyncTaskLoader を使っています。
package jp.inujirushi.android.sample;

import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.widget.Toast;

public class SampleActivity extends FragmentActivity implements
LoaderCallbacks<Boolean> {

// Activity が生成された時に呼ばれます
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);

// Loader を実行する
// 第2引数で onCreateLoader に渡される Bundle を指定するがこのサンプルでは使用しないので null
getSupportLoaderManager().initLoader(0, null, this);
}

// Loader を新規作成する時に呼ばれます。
// 戻り値には実行する Loader を指定してください。
// AsyncTask#onPreExecute() で行っていた処理もここに記述します。
@Override
public Loader<Boolean> onCreateLoader(int id, Bundle bundle) {
// ProgressDialog を生成する
TestProgressDialog dialog = new TestProgressDialog();
Bundle args = new Bundle();
args.putString(TestProgressDialog.PARAM_MESSAGE, "now loaging...");
dialog.setArguments(args);

// ProgressDialog をキャンセルしたら Loader もキャンセルするよう設定する
dialog.setCancelable(true);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
Loader<Object> loader = getSupportLoaderManager().getLoader(0);
// Loader をキャンセルする
if (loader != null) {
((AsyncTaskLoader<?>) loader).cancelLoad();
}
}
});

// ProgressDialog を表示する
dialog.show(getSupportFragmentManager(), "progress");

// 生成した Loader を返します
return new SampleAsyncTaskLoader(this);
}

// Loader の処理が完了した時に呼ばれます。
// キャンセル時には呼ばれません。
// AsyncTask#onPostExecute() で行っていた処理はここに記述します。
@Override
public void onLoadFinished(Loader<Boolean> loader, Boolean result) {
// ProgressDialog を破棄する
TestProgressDialog dialog = (TestProgressDialog) getSupportFragmentManager()
.findFragmentByTag("progress");
if (dialog != null) {
dialog.onDismiss(dialog.getDialog());
}

// 結果をトースト表示する
Toast.makeText(this, "result=" + result, Toast.LENGTH_SHORT).show();
}

// Loader が完全に破棄される時に呼ばれます。
@Override
public void onLoaderReset(Loader<Boolean> loader) {
}

/**
* Loader 処理クラス。
*/
static class SampleAsyncTaskLoader extends AsyncTaskLoader<Boolean> {
/**
* コンストラクタ。
* @param context
* コンストラクタ
*/
public SampleAsyncTaskLoader(Context context) {
super(context);
}

// 非同期処理を行います。
// キャンセル有無にかかわらず処理は最後まで流れます。
@Override
public Boolean loadInBackground() {
// 10秒間処理をしているように見せかけるためスリープ
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
}

// キャンセルされた時に呼ばれます。
// この処理は loadInBackground() の完了後に行われます。
@Override
public void onCanceled(Boolean data) {
}

// Loader が開始された時に呼ばれます。
@Override
protected void onStartLoading() {
// Loader を開始する
forceLoad();
}
}
}
非同期処理の流れ
① FragmentActivity#getSupportLoaderManager().initLoader()
② LoaderCallbacks#onCreateLoader()
③ AsyncTaskLoader#onStartLoading()
④ AsyncTaskLoader#loadInBackground()
⑤ LoaderCallbacks#onLoadFinished() ※キャンセル時は AsyncTaskLoader#onCanceled()

④の非同期処理は③で AsyncTaskLoader#forceLoad() を呼ぶ必要があります。
呼ばなかった場合、非同期処理は行われません(…ここで少しはまりました…)


■ 参考サイト
ソフトウェア技術ドキュメントを勝手に翻訳 - 1.2 ローダ
TechBooster - AsyncTaskLoaderを利用した非同期処理を行う
クラスメソッド Developers.IO - AsyncTaskLoaderを使ってみる
コジオニルク - 1.11. AsyncTaskLoader
スポンサーサイト



プロフィール

とむ・やむくん

Author:とむ・やむくん
管理人について

Windows 7 / 64bit
Eclipse 4.2 Juno (日本語パッチ済)

スポンサーサイト
最新トラックバック
検索フォーム
ブロとも申請フォーム
QRコード
QR
Twitter
2013/01/04 19:00 カウント開始