8

この質問は、これを読んだ後に私に来ました:パフォーマンスのヒント(具体的には「非同期読み込み」という名前の部分)。基本的に、彼は行に関する情報を保存して、まだリサイクルされているかどうかを確認し、行がまだ表示されている場合にのみダウンロードした画像を設定しようとしています。これは彼がポジションを保存する方法です:

holder.position = position;

new ThumbnailTask(position, holder)
        .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);

ThumbnailTask​​ コンストラクターの場所:

public ThumbnailTask(int position, ViewHolder holder) {
    mPosition = position;
    mHolder = holder;
}

onPostExecute() で、前述のチェックを行います。

    if (mHolder.position == mPosition) {
        mHolder.thumbnail.setImageBitmap(bitmap);
    }

これがどのように結果をもたらすかわかりません。ホルダーと位置はコンストラクターで同時に同じ値に設定されます (ホルダー内の位置は mPosition 内の位置と同じです)。それらは AsyncTask 中に変更されません (getView() で位置が変更される可能性があるのは事実ですが、プライベート メンバーとして AsyncTask に格納されているものは操作されません)。ここで何が欠けていますか?

また、位置を保存することは、そもそも良い選択肢のようには思えません。一意であることが保証されていないと思います。正しく思い出せば、スクロール後に0にリセットされます。私は正しい方向に考えていますか?

4

4 に答える 4

4

AsyncTask が渡されViewHolder、 ViewHolder オブジェクトへのpositionposition(たとえば5) と参照の値(コピーではない) が渡される場合。彼はまた、現在の位置を ViewHolder に入れます (言った5) が、ここでの「トリック」全体は、リサイクルされたビューの場合、古い ViewHolder オブジェクトも再利用されることです (リンクされた記事):

} else {
   holder = convertView.getTag();
}

したがって、その特定の ViewHolder オブジェクトを参照するコードは、実際には、オブジェクトの作成時ではなく、check の実行時にpositionそのメンバー値に対してチェックされます。タスク コンストラクターに渡される値はプリミティブであるため変更されない (この場合は の値を持つ) ため、このチェックは理にかなっていますが、 に到達する前にビューが再利用される場合、ViewHolder オブジェクトはそのプロパティを変更できます。onPostExecuteposition5onPostExecute

タスクのコンストラクターで ViewHolder オブジェクトをコピーしないことに注意してください。それは Java の仕組みではありません :)説明については、この記事を参照してください

また、位置を保存することは良い選択肢のようには思えません。それが一意であるとは限らず、スクロール後にゼロにリセットされると思います。これは本当ですか?

いいえ。ここでの位置は *ソース データ セット内のインデックスを意味し、画面には表示されません。したがって、表示する項目が 10 個あっても、一度に画面に 3 個しか収まらないposition場合、範囲は 0 ~ 9 になり、行の可視性は問題になりません。

于 2013-08-08T21:26:43.757 に答える
0

受け入れられた答えとMarcinの投稿は、何が起こるべきかをすでに完全に説明しています。ただし、リンクされた Web ページはそうではなく、このトピックに関する Google サイトも非常に曖昧であり、「トリック」について既に知っている人のための参照のみです。したがって、今後の参考のために、getView()への必要な追加を示す欠落部分を次に示します。

// The adapter's getView method
public View getView(int position, View convertView, ViewGroup parent) {
    // Define View that is going to be returned by Adapter
    View newViewItem;
    ViewHolder holder;

    // Recycle View if possible
    if (convertView == null) {
        // No view recycled, create a new one
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        newViewItem = inflater.inflate(R.layout.image_grid_view_item, null);

        // Attach a new viewholder
        holder = new ViewHolder();
        holder.thumbnail = (ImageView) newViewItem.findViewById(R.id.imageGridViewItemThumbnail);
        holder.position = position;
        newViewItem.setTag(holder);
    } else {
        // Modify "recycled" viewHolder
        holder = (ViewHolder) convertView.getTag();
        holder.thumbnail = (ImageView) convertView.findViewById(R.id.imageGridViewItemThumbnail);
        holder.position = position;

        // Re-use convertView
        newViewItem = convertView;
    }
    // Execute AsyncTask for image operation (load, decode, whatever)
    new LoadThumbnailTask(position, holder).execute();

    // Return the ImageView
    return newViewItem;
}

// ViewHolder class, can be implemented inside adapter class
static class ViewHolder {
    ImageView thumbnail;
    int position;
}
于 2015-03-06T17:42:56.117 に答える