【问题标题】:Android ListView notifyDataSetChangedAndroid ListView notifyDataSetChanged
【发布时间】:2011-09-04 20:36:35
【问题描述】:

我有一个自定义列表视图,每个条目都包含旋转的 ProgressBar 和单行文本视图。我总是只更新列表中的第一项。问题是每次我调用 notifyDataSetChanged 时,所有可见视图要么被重新创建,要么被回收为 convertView。

这种方法有两个问题:

  • 重新创建所有条目,这很慢 - 这不是必需的,因为我只更新第一个条目中的文本视图

  • ProgressBar 动画每次都会重新启动

所以我只保留对适配器中第一个视图的引用并手动更新它。它有效,但它随机抛出 IllegalStateException(“适配器的内容已更改,但 ListView 未收到通知。确保您的适配器的内容不是从后台线程修改的,而只是从 UI 线程修改的。”)

我该如何解决?有没有办法通知 ListView 只有第一个条目发生了变化?即使有,ProgressBar 动画仍然会失败。有没有其他方法可以手动更新?

谢谢

【问题讨论】:

  • 你能显示执行更新的代码吗?从消息看来,您可能正在通过非 UI 线程更新 UI(例如 AsyncTask 中的 doInBackground())
  • 发帖太复杂了,不过在UI线程上。问题在于没有调用 notifyDataSetChanged,正如我在问题中所解释的那样。
  • 我也有同样的问题。我在 UIThread 中使用了关于列表和适配器的所有方法。但是随机抛出这个异常。你是怎么解决的?

标签: android listview progress-bar adapter


【解决方案1】:

每当我需要更新列表视图上的一个项目时,我都会使用这个:

public void updateItemAt(int index) {
    View v = listView.getChildAt(index - listView.getFirstVisiblePosition());
    if (v != null) {
        //updates the view
    }
}

缺点是您需要在适配器中保存对 listView 的引用。 由于此代码通常是从后台任务中调用的,因此您必须使用处理程序来调用它:

Handler myHandler = new Handler() {
    public void handleMessage(Message msg) {
        int index = msg.what;
        myAdapter.updateItemAt(index);
    };
};

//when task is complete:
myHandler.sendEmptyMessage(index);

【讨论】:

  • 请再次阅读问题。即使从 UI 线程进行更改,ListView 也需要调用 notifyDataSetChanged。您的解决方案也会随机抛出上述异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 2013-01-08
  • 2011-09-16
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多