异步更改 ListView 中的特定项目

Posted

技术标签:

【中文标题】异步更改 ListView 中的特定项目【英文标题】:Asynchronously change a particular item in a ListView 【发布时间】:2014-02-05 10:02:56 【问题描述】:

所以我在ListView 中有一个作业名称列表,它是由扩展BaseAdapter 的自定义适配器生成的。所有项目最初都显示为灰色。对于每个项目,我通过 Web 服务发送一个异步请求,以获取该作业的状态。同时,我在每一行都显示了一个不定的进度条。每次收到响应时,都会为该特定项目调用回调方法 onSuccess(int itemPosition)。 itemPosition 是列表中项目的索引。在这种方法中,我想根据收到的状态设置文本的颜色并删除进度条。我尝试了以下方法,但没有成功:

public void onSuccess(int itemPosition, int status) 
    View convertView = getLayoutInflater().inflate(R.layout.rowlayout, null);
    ((ProgressBar)convertView.findViewById(R.id.progressbar)).setVisibility(ProgressBar.GONE);
    if(status == READY)
        ((TextView)convertView.findViewById(R.id.jobname))
              .setTextColor(status == READY ? Color.GREEN : Color.RED);
        mListViewAdapter.getView(itemPosition, convertView, null);
    

任何想法我应该如何处理?

【问题讨论】:

不要调用 getView 你自己。始终修改底层数据,通知适配器,让其处理视图的刷新。 谢谢,但我有以下问题。该列表是“作业”对象的列表。此对象没有显示响应是否已收到的字段。有什么方法可以从外部而不是从 getView() 控制进度条的可见性? 而且,我不希望刷新整个列表,尽管只触及了一项。 不用担心整个列表会被刷新,只有可见元素会刷新,双缓冲确保你看不到它。无论如何,您无法对 listview 处理其视图的方式进行任何形式的控制。您需要为适配器提供一些数据以使其更改视图。将这些数据放入工作中是最明智的方式,恕我直言 ***.com/a/2679284/1405008 参考这个更简洁的解决方案,仅在 UI 显示在屏幕上时更新它。 【参考方案1】:

涉及编辑特定 Views 的任何其他答案都不是解决方案 - 当您滚动时它们将失败并且那些 ListView 行被回收!当您滚动时,ListView 将不断使用Jobs 的列表/数组/任何内容来重新填充自己。更不用说,您的 ListView 不会拥有与 Jobs 一样多的行,它只会有填满屏幕所需的行数。因此,您甚至无法访问与当前不可见的作业相关的行。根据所使用的设备、方向以及将来如果您更改此屏幕的布局,可见行/作业的数量会有所不同,从而使这个“解决方案”变得更糟。

假设您的自定义Adapter 由作为适配器成员的Jobs(或您决定支持它的任何数据结构)的Array 支持,只需更改Array 然后在适配器上调用notifyDataSetChanged。这正是notifyDataSetChanged 的用途,您不会注意到整个ListView 的刷新。如果您希望优化您的 ListView 性能,至少要确保您没有在每个 getView 调用中夸大行视图,然后另外实现 ViewHolder pattern。

【讨论】:

【参考方案2】:

njzk2 是对的。您可以在您的适配器中设置一个 HashMap,该 HashMap 存储指定 Job 对象的“正在运行”或“已下载”状态。 适配器中的方法允许您设置此信息。在您的 getView 中,检查已膨胀的 Job 对象是否“正在运行”或“已下载”并显示您想要的内容。即使您有一个 convertView,也必须进行此检查。

【讨论】:

在适配器中保存一个单独的 HashMap 是一个好主意。谢谢!【参考方案3】:

尝试在您的活动中执行此操作:

public void onSuccess(int itemPosition, int status) 
View childView = yourListView.getChildAt(itemPostion);
((ProgressBar)childView.findViewById(R.id.progressbar)).setVisibility(ProgressBar.GONE);
if(status == READY)
    ((TextView)childView.findViewById(R.id.jobname))
          .setTextColor(status == READY ? Color.GREEN : Color.RED);


【讨论】:

以上是关于异步更改 ListView 中的特定项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Sqlite 数据库中的特定数据上更改 Listview 中的行颜色

从ArrayAdapter每毫秒更新Android ListView中的一行

从 ListView 更改特定元素

如何在颤动/飞镖的 ListView 项目中更改背景颜色

在 Android 中的顶部 ListView 项目上方(以及最后一个项目下方)添加边距

Android,ListView IllegalStateException:“适配器的内容已更改但ListView没有收到通知”