为什么这个涉及ListView,ArrayAdapter和视图持有者的代码没有按预期工作?

时间:2015-08-28 11:48:39

标签: android listview android-arrayadapter

我尝试使用ListView创建ArrayAdapter<T>,其中T类型作为视图持有者第二次使用。这可能看起来有点奇怪,但这背后的想法是我可以编写一个onClick(View view)方法,该方法以view.getTag()行开头,直接转到T View的实例public class MyActivity extends Activity { private static final class ViewHolder { private final String string; private TextView textView; private ViewHolder(String string) { this.string = string; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); final List<ViewHolder> viewHolders = new ArrayList<ViewHolder>(); for (int i = 0; i < 20; i++) { viewHolders.add(new ViewHolder("A")); viewHolders.add(new ViewHolder("B")); viewHolders.add(new ViewHolder("C")); } final ArrayAdapter<ViewHolder> adapter = new ArrayAdapter<ViewHolder>(this, -1, viewHolders) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view; TextView textView; if (convertView == null) { view = getLayoutInflater().inflate(R.layout.item_layout, parent, false); textView = (TextView) view.findViewById(R.id.text_view); } else { view = convertView; textView = ((ViewHolder) convertView.getTag()).textView; } ViewHolder viewHolder = viewHolders.get(position); textView.setText(viewHolder.string); viewHolder.textView = textView; view.setTag(viewHolder); return view; } }; ((ListView) findViewById(R.id.list_view)).setAdapter(adapter); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Collections.rotate(viewHolders, 1); adapter.notifyDataSetChanged(); } }); } } 1}}是从。

创建的

这是代码。

convertView

我无法理解为什么这不起作用。在这两种情况下(null是或不是View),您始终会返回包含TextView的{​​{1}},其中文本已设置为viewHolders.get(position).string }。当然,尽管这种方法很复杂,但您应该始终看到ABCABC等? ViewHolder有60个不同的实例,你在屏幕上的两个地方永远不会有相同的TextView,因为你传递的convertView应该来自屏幕外的位置?我明显错了,因为点击旋转几次之后订单就会搞砸了。如果有人能向我解释,我真的很感激。

以下是activity_my.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/button"
        android:paddingBottom="5dp"
        android:paddingTop="5dp"
        android:text="Rotate"
        android:textSize="24sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>
</LinearLayout>

以下是item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:textSize="24sp"
        android:gravity="center"
        />
</LinearLayout>

1 个答案:

答案 0 :(得分:0)

这非常令人困惑,但我想我已经弄清楚这是怎么发生的。

  • 第1步:为getView ViewHolder调用h,并返回View v

现在v.getTag() == hh.textViewTextView中的v

  • 第2步:为同一getView ViewHolder调用h,但这次会返回不同的View w

此时w.getTag() == hh.textView已更改为TextView中的w

  • 第3步:调用getViewconvertView使用的是v

此时v.getTag()仍然是h从步骤1开始,但h.textView已更改为步骤2中TextView中的w。这意味着行textView.setText(viewHolder.string);实际上并未将文本设置为正确的TextView