まず問題:Android - スレッドプール戦略とそれを実装するためにLoaderを使用できますか?
- 私はカスタマイズ
FragmentStatePagerAdapter
内で複数のFragmentLists
を使用するアプリケーションに取り組んでいます。 このようなフラグメントの潜在的にかなりの数は、20と40の間にある可能性があります。 - 各フラグメントは、各アイテムがテキストまたはイメージを含むことができるリストです。
- 利用可能な場合、フラグメントが画面の外になると画像が
私の最初の実装は、Googleのよく知られたimage loader codeに続いています。そのコードの私の問題は、基本的に画像ごとにAsyncTask
という1つのインスタンスを作成するということです。私の場合は本当に速くアプリを殺す。
私はv4互換のパッケージを使用していますので、AsyncTaskLoader
を拡張するカスタムローダーを使用すると、内部的にスレッドプールが実装されていると思います。しかし、このコードを複数回実行すると、私の不愉快な驚きにもかかわらず、それぞれの呼び出しがそれを中断します。このメソッドは見えてくる各リスト項目のためのループ内で実行される
getSupportLoaderManager().restartLoader(0, args, listener);
:私は私のListView#getView
方法でこれを持っていると言います。私が述べたように、それぞれの呼び出しは前の呼び出しを終了します。あるいは、少なくともそれは、その後、私は多分問題を助けます各ローダーに一意のIDを与えるが、すべての違いを確認していないようだと思った
11-03 13:33:34.910: V/LoaderManager(14313): restartLoader in LoaderManager: args=Bundle[{URL=http://blah-blah/pm.png}]
11-03 13:33:34.920: V/LoaderManager(14313): Removing pending loader: LoaderInfo{405d44c0 #2147483647 : ImageLoader{405118a8}}
11-03 13:33:34.920: V/LoaderManager(14313): Destroying: LoaderInfo{405d44c0 #2147483647 : ImageLoader{405118a8}}
11-03 13:33:34.920: V/LoaderManager(14313): Enqueuing as new pending loader
LogCat
に基づいて起こるものです。結果として、私は一見無作為の画像で終わり、アプリは私が必要とするものの1/4までを読み込むことはありません。私がやりたいローダーを修正する方法だろうどのような質問
- (および方法はありますか?)
- 何
AsyncTask
プールを作成するための良い方法であるとされていない場合おそらくそれの実装を実装している?
実際のダウンロード/保存ロジックが別のImageManagerクラスにあるローダのバージョンを削除したコードをここに示します。
public class ImageLoader extends AsyncTaskLoader<TaggedDrawable> {
private static final String TAG = ImageLoader.class.getName();
/** Wrapper around BitmapDrawable that adds String field to id the drawable */
TaggedDrawable img;
private final String url;
private final File cacheDir;
private final HttpClient client;
/**
* @param context
*/
public ImageLoader(final Context context, final String url, final File cacheDir, final HttpClient client) {
super(context);
this.url = url;
this.cacheDir = cacheDir;
this.client = client;
}
@Override
public TaggedDrawable loadInBackground() {
Bitmap b = null;
// first attempt to load file from SD
final File f = new File(this.cacheDir, ImageManager.getNameFromUrl(url));
if (f.exists()) {
b = BitmapFactory.decodeFile(f.getPath());
} else {
b = ImageManager.downloadBitmap(url, client);
if (b != null) {
ImageManager.saveToSD(url, cacheDir, b);
}
}
return new TaggedDrawable(url, b);
}
@Override
protected void onStartLoading() {
if (this.img != null) {
// If we currently have a result available, deliver it immediately.
deliverResult(this.img);
} else {
forceLoad();
}
}
@Override
public void deliverResult(final TaggedDrawable img) {
this.img = img;
if (isStarted()) {
// If the Loader is currently started, we can immediately deliver its results.
super.deliverResult(img);
}
}
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
if (this.img != null) {
this.img = null;
}
}
}
'AsyncTask'はすでにプールを使用しています。プールは、あなたの難しさの原因となる可能性がある、最大で128スレッドのIIRCスレッドになります。 'java.util.concurrent'クラスを使って独自のスレッドプールを実装できます。 – CommonsWare
開発がAndroid 3.0(APIレベル11)をターゲットにしている場合は、新しく追加されたAPI [AsyncTask.executeOnExecutor()](http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor% 28Java.util.concurrent.Executor、%20Params ...%29)AsyncTask作成ライフサイクルでスレッドプールを細かく制御します。 – yorkw
それにもかかわらず、AsynkTaskは1回しか実行できないので、イメージごとに1つのインスタンスを作成する必要があります。それを60にするとそれは多くのオブジェクトです – Bostone