在 BaseAdapter 上的列表显示错误

我设置的 Adapter 是 BaseAdapter,部分代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag;
if(convertView == null) {
convertView = myInflater.inflate(R.layout.myrow, null);
viewTag = new ViewTag((ImageView)convertView.findViewById(R.id.myicon),  (TextView)convertView.findViewById(R.id.mytext));
convertView.setTag(viewTag);
}
else {
viewTag = (ViewTag) convertView.getTag();
}
viewTag.mytext.setText(MyTitle[position]);
if(Icon[position].equals("Yes")) {
viewTag.myicon.setVisibility(View.VISIBLE);
}
else {
viewTag.myicon.setVisibility(View.INVISIBLE);
}
}
class ViewTag {
ImageView myicon;
TextView mytext;
public ViewTag(ImageView iv1, TextView tv1) {
this.myicon = iv1;
this.mytext = tv1;
}
}

在 Activity 中使用下面的代码调用:

private Runnable updateRunnable = new Runnable() { 
public void run() {
MyAdapter.notifyDataSetChanged();
handler.postDelayed(updateRunnable, 1000);
}
};

为什么图标显示错误?和图标数组不一样。图标数组总是显示"Yes"。所以列表应该每次只显示一个图标,但是有时候显示好几个图标,如何修改?

这里有几点可能会导致问题的地方:

  • 在调用 notifyDataSetChanged 方法时,ListView 会重新调用 getView 方法来获取每一项的视图,所以在 getView 方法中,有一个 if(convertView == null) 的判断来决定是否需要重新创建新的视图。如果 convertView 不为 null,则可以直接使用这个 convertView,避免了重新创建新的视图。因此,如果你在调用 notifyDataSetChanged 时,数据源(例如 Icon 数组)已经发生了改变,而 getView 方法中没有相应地更新数据,就可能会导致问题。
  • 在调用 notifyDataSetChanged 方法后,ListView 会刷新视图。如果在这个过程中,你的 Runnable 又重新调用了 notifyDataSetChanged 方法,就会导致视图被多次刷新,从而导致图标显示错误。

为了解决这个问题,你可以尝试在 getView 方法中,正确地更新数据,并且在调用 notifyDataSetChanged 方法之后,稍微延迟一段时间再调用下一次 notifyDataSetChanged。这样就可以避免在刷新视图的过程中,又重新调用了 notifyDataSetChanged 方法。


例如,你可以把代码改成这样:

private Runnable updateRunnable = new Runnable() {
    public void run() {
        MyAdapter.notifyDataSetChanged();
        handler.postDelayed(updateRunnable, 1000);
    }
};

然后你可以在 getView 方法中,正确地更新数据。例如:

@Override public View getView(int position, View convertView, ViewGroup parent) {
    ViewTag viewTag;
    if (convertView == null) {
        convertView = myInflater.inflate(R.layout.myrow, null);
        viewTag = new ViewTag((ImageView) convertView.findViewById(R.id.myicon), (TextView) convertView.findViewById(R.id.mytext));
        convertView.setTag(viewTag);
    } else {
        viewTag = (ViewTag) convertView.getTag();
    }

    // 更新数据
    viewTag.mytext.setText(MyTitle[position]);
    if (Icon[position].equals("Yes")) {
        viewTag.myicon.setVisibility(View.VISIBLE);
    } else {
        viewTag.myicon.setVisibility(View.INVISIBLE);
    }
}

class ViewTag {
    ImageView myicon;
    TextView mytext;
    public ViewTag(ImageView iv1, TextView tv1) {
        this.myicon = iv1;
        this.mytext = tv1;
    }
}

这样就可以正确地刷新视图,避免了图标显示错误的问题。