1

私は EventAdapter で ListView を持っています。

public class EventAdapter extends BaseAdapter {
...
public View getView(int position, View view, ViewGroup parent) {
     ...
     cache.imgIcon.setImageDrawable(ImgCache.setImg(url, progressBar));
     ...
}

ImgCache は、画像をキャッシュするためのクラスです。

public class ImgCache {
    public static HashMap<String, Drawable> imgCache;

    // get img from cache if exist, or download and put in cache
    public static Drawable setImg(final String link, final ProgressBar progressBar) {
        final Drawable[] image = {null};
        if (imgCache.containsKey(link)) {
            image[0] = imgCache.get(link);
            progressBar.setVisibility(View.INVISIBLE);
        } else {
            new AsyncTask<Void, Void, Drawable>() {
                @Override
                protected Drawable doInBackground(Void... params) {
                    URL url = null;
                    try {
                        url = new URL(link);
                        URLConnection connection = url.openConnection();
                        image[0] = Drawable.createFromStream(connection.getInputStream(), "src");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    imgCache.put(link, image[0]);
                    return image[0];
                }

                @Override
                protected void onPostExecute(Drawable result) {
                    progressBar.setVisibility(View.INVISIBLE);
                }
            }.execute();
        }
        return image[0];
    }
}

問題は何ですか?

Activityすべての画像を開いた後、ListView読み込みが開始されます。しかし、ロードが完了した後、それらは表示されません。次のようになります。

ここに画像の説明を入力

次に、2項目下にスクロールしてから、前の位置に戻ろうとします。この操作の後、画像付きの 2 つの上部アイテムが表示されます。また、下にあるすべての画像は、スクロールすると表示されます。

ここに画像の説明を入力

4

3 に答える 3

2

AsyncTaskは非同期であるため、アプリのフローは次のようになります。

ListView アイテムを表示する必要があります -> リスト アイテムの Adapter.getView(...) を呼び出します -> 画像がキャッシュにない場合は、AsyncTask を実行して (結果を待たずに) 戻ります。 Adapter.get(...) メソッドが再度呼び出されますが、今回は画像がキャッシュにあるため、表示される Drawable オブジェクトを返します

この問題を解決する 1 つの方法は、AsyncTask からアダプタへのコールバックを使用して、アダプタを呼び出しnotifyDataSetChangedて取得した画像を更新し、特定の Drawable を直接設定するか、同様のものを設定することです (その間に画像の読み込み gif を表示しますか? )

または

get(long timeout, TimeUnit unit)マン スレッドをブロックし、AsyncTask が完了するまで待機するAsyncTask メソッドを呼び出します。終了すると、結果が返されます (この場合は Drawable)。これにより、画像のフェッチ中にメインの UI スレッドがハングするため、最適な方法ではありません。

于 2013-04-16T14:52:52.290 に答える