25

これをグーグルで検索しましたが、答えが見つからないので、ここに行きます...

テキストと画像を表示する ListView があります。基になるアダプターは、パフォーマンス上の理由から (推奨されるアプローチに従って) ビューをリサイクルし、Android 開発者サイトのビットマップ ページにある推奨に従って、AsynchTask を使用して画像を読み込みます。

すべてが完璧かつスムーズに機能しますが、問題が 1 つあります。アダプター内のビューがリサイクルされると、古いイメージ (ImageView) への参照がまだ残っています。ユーザーのスクロールが遅い場合、AsynchTask には新しい画像を読み込んで表示するのに十分な時間があるため、新しい画像の再読み込みがユーザーに表示されることはありません。

ただし、ユーザーが非常に速くスクロールした場合、画像の読み込みに時間がかかるため、新しい画像に置き換えられる前に古い画像 (View が別の項目で使用されていたときに読み込まれたもの) が表示されます。

だから、私の質問は、ビューが画面に表示されなくなったことをどのように検出して、画像を削除できるかということです。これは、最終的には適切な画像が読み込まれる空のリスト ビュー アイテムがユーザーに表示されることを意味し、より見栄えが良くなります。

よろしくお願いします。リスト ビュー アダプターのコードは次のとおりです。

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    ListViewHolder viewHolder;

    // if this is not a recycled view then create a new view for the data...
    if (view == null)
    {
        view = this.inflater.inflate(R.layout.target_list_view_layout, null, true);

        viewHolder = new ListViewHolder();

        viewHolder.manufacturer = (TextView) view.findViewById(R.id.manufacturer);
        viewHolder.targetName = (TextView) view.findViewById(R.id.targetName);
        viewHolder.targetThumbnail = (ImageView) view.findViewById(R.id.targetThumbnail);

        view.setTag(viewHolder);
    } else
    {
        viewHolder = (ListViewHolder) convertView.getTag();
    }

    TargetDescriptor targetDescriptor = this.selectedTargets.get(position);

    viewHolder.manufacturer.setText(targetDescriptor.manufacturer);
    viewHolder.targetName.setText(targetDescriptor.targetName);

    // At this point I pass the image view reference to my background task to load the image
    LoadImageViewAsynchTask loadImageTask = new LoadImageViewAsynchTask(viewHolder.targetThumbnail, targetDescriptor);
    loadImageTask.execute(new Integer[]
    { 64, 64 });

    return view;
}

編集: eBay Android アプリを使用している人は、私が探している効果を確認できます。

4

4 に答える 4

28

実際には、より簡単な方法があります。リスナーを使用できます。

mListView.setRecyclerListener(new AbsListView.RecyclerListener() {
@Override
    public void onMovedToScrapHeap(View view) {
  }
});
于 2014-10-23T13:43:22.237 に答える
0

ビットマップに LruCache を使用し、リストビューの各ビューに LruCache アイテムのキーを保持させると、より適切に制御できます。次に、getView で、最初に LruCache からビットマップを取得して、再度ダウンロードするだけにします。そこにない場合。

また、ListView に setOnScrollListener() を設定し、その visibleItemCount パラメータを使用して、ユーザーが最初にスクロールしたときに LruCache のサイズを調整することもできます。

于 2013-10-27T19:18:25.090 に答える
-1

画像を表示するためにオーバーライドさgetViewれたメソッドを使用している場合は、convertView を確認できます。null の場合は、リサイクルされたか、以前に初期化されていないことがわかります。単純に次のように:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    ViewHolder viewholder;
    if (convertView == null) {
        viewholder = new ViewHolder();
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.item_row, parent, false);
        viewholder.tvID = (TextView) convertView.findViewById(R.id.tvID);
        viewholder.tvName = (TextView) convertView.findViewById(R.id.tvName);
        viewholder.tvFamily = (TextView) convertView.findViewById(R.id.tvFamily);
        viewholder.ivMain = (ImageView) convertView.findViewById(R.id.ivMain);
    } else {
        viewholder = (ViewHolder) convertView.getTag();
    }
    viewholder.tvID.setText(IDs[position]);
    viewholder.tvName.setText(Names[position]);
    viewholder.tvFamily.setText(Familys[position]);
    viewholder.ivMain.setImageResource(Images[position]);
    convertView.setTag(viewholder);
    return convertView;
}
于 2013-10-27T18:13:20.247 に答える