2
public View getView(int index, View view, ViewGroup parent){
    if (view == null) { // for the first time, inflate the view
        LayoutInflater inflater =
            LayoutInflater.from(parent.getContext());
        view = inflater.inflate(
            R.layout.time_list_item, parent, false);
    }
    /**
    * The layout under consideration has two TextViews in it
    * one to display the time and other to display some text.
    */
    TimeRecord time = times.get(index);
    timeTextView.setText(time.getTime());
    TextView timeTextView = (TextView)
    view.findViewById(R.id.time_view);
    notesTextView.setText(time.getNotes());
    TextView notesTextView = (TextView)
    view.findViewById(R.id.notes_view);

    return view;
}  

getView()表示されるコレクションのすべてのアイテムに対して繰り返し呼び出されることを知っています。私が使用している参照では、パフォーマンスを最適化するには、ビューを再利用する必要があると述べています。さて、この「再利用」は私を混乱させます。

これらの返されたビューは、に表示されますListViewView新しいデータを再入力したものだけを返す場合、データはどのように適切に表示されますか? どうすれば複数のエントリが存在できますか?
つまり、単一のビューを返すだけで、複数のListViewエントリが表示されることを期待していませんか? 私は新しいものを返すべきではありませんViewsか?

4

3 に答える 3

3

getView() はカスタム アダプタでどのように機能しますか?

getView() メソッドは、各行が独自のビューを持つ行の数と同じ回数呼び出されます。

さて、この「再利用」は私を混乱させます。

ビューのリサイクルと呼ばれます。つまり、行が表示されていない場合、null ではありません (作成され、少なくとも 1 回表示されている場合) が、行の子ビューを保持するメカニズムを作成しない場合、リサイクルは機能せず、あなたの場合は findViewById()行ごとに呼び出されます (たとえば、1000 行の場合、あまり効率的ではありません)。

この目的のためにホルダーデザインパターンが使用されます。各行の子ビューの参照を保持する単純な任意のオブジェクトです。

次のように実装できます。

public class RowHolder {

   private View row;

   // childs widgets in row
   private TextView name;

   public RowHolder(View row) {
      this.row = row; // row in ListView (in your case)
   }

   public TextView getName() {
      if (name == null) {
         name = (TextView) row.findViewById(<id>);
      }
      return name;
   }

   ...
}

そして使用法:

LayoutInflater inflater;
RowHolder holder = null;

// row created first time
if (convertView == null) {
   convertView = inflater.inflate(<rowXMLLayout>, null, false);
   holder = new RowHolder(convertView); // adding row to arbitrary obj
   convertView.setTag(holder) // adding this obj to row at position
}
else {
  // recycling started
  holder = (RowHolder) convertView.getTag();
}


// updating rows
holder.getName().setText(<value?>);
...
于 2013-08-05T08:26:33.947 に答える
1

Recycling という名前の ListView でのこの動作。ListView のリサイクル メカニズムのしくみView Recycling in ListViewの詳細を確認できます。

于 2013-08-05T08:20:12.970 に答える
1

したがって、ListView はカスタム アダプタを次のように使用します。

  • 表示されているビューと画面外にあるいくつかのビューを膨らませて、後で表示する準備をします。
  • メソッド getView() を呼び出してビューを拡張します。
  • その結果、ビューは ListView 内の弱参照配列に保存されます。つまり、アプリがメモリ不足になったときに、ガベージ コレクターによってビューが削除される可能性があります。

利点は、getView で RECYCLED VIEW を適切に再利用すると、コマンド inflate() が 1 回だけ呼び出される場合があることです (ただし、すべてのリスト項目ではなく、必要でない場合)。そして、この膨張は非常に遅いので省略したいと思います。

そして、この配列には、カスタム アダプターが getViewTypeCount() で返すのと同じ数の入り口があります。単純なリストビューでは、それはちょうど 1 になります。そのため、このリサイクルを getView(int インデックス、リサイクルされたビューを表示、親のビュー) で実行すると、パラメータとして毎回同じリサイクルされたビューを取得することになります。 textViews、画像などのプロパティなので、必要なものが含まれています。言い換えれば、リストのすべてのアイテムは同じように見えるわけではありませんが、レイアウトが同じであるため、似ています (文字通り同じレイアウト ファイルとマージン、幅などの同じレイアウト)。

リストビューでいくつかのビューを使用している場合、つまり、1 つのビューを膨らませると、それ以外の場合は異なります。getViewTypeCount() と getItemViewType() をオーバーライドして、リストのどのインデックスがどのビューを取得するかを Listview が認識できるようにする必要があります。

于 2013-08-05T08:30:24.097 に答える