如何更新ListView中的单行?

Eri*_*rik 130 android android-arrayadapter android-listview

我有一个ListView显示新闻项目.它们包含图像,标题和一些文本.图像被加载到一个单独的线程(带有队列和所有)中,当下载图像时,我现在调用notifyDataSetChanged()列表适配器来更新图像.这是有效的,但是getView()因为notifyDataSetChanged()调用getView()了所有可见的项目而被过于频繁地调用.我想只更新列表中的单个项目.我该怎么做?

我目前使用的方法存在的问题是:

  1. 滚动很慢
  2. 我在图像上有一个淡入动画,每次加载列表中的一个新图像时都会发生这种动画.

Eri*_*rik 197

我找到了答案,感谢你的信息米歇尔.你确实可以使用正确的视图View#getChildAt(int index).问题是它从第一个可见项开始计数.实际上,您只能获取可见项目.你解决这个问题ListView#getFirstVisiblePosition().

例:

private void updateView(int index){
    View v = yourListView.getChildAt(index - 
        yourListView.getFirstVisiblePosition());

    if(v == null)
       return;

    TextView someText = (TextView) v.findViewById(R.id.sometextview);
    someText.setText("Hi! I updated you manually!");
}
Run Code Online (Sandbox Code Playgroud)

  • 自我注意:mImgView.setImageURI()将更新列表项但只更新一次; 所以我最好使用mLstVwAdapter.notifyDataSetInvalidated()代替. (2认同)
  • 效果很好。它可以帮助我完成在类似instagram的应用中实现“赞”功能的任务。我正在使用一个自定义适配器,在list元素内的like按钮中广播,启动一个asynctask以父片段上的广播接收器来告诉后端有关like的消息,最后是Erik的答案来更新列表。 (2认同)

mre*_*elt 71

这个问题已在Google I/O 2010上提出,您可以在此处观看:

ListView的世界,时间52:30

基本上什么罗曼盖伊解释是调用getChildAt(int)ListView得到的看法和(我认为)调用getFirstVisiblePosition(),找出位置和指数之间的相关性.

Romain也指出了名为Shelves的项目作为一个例子,我认为他可能意味着方法ShelvesActivity.updateBookCovers(),但我找不到调用getFirstVisiblePosition().

令人敬畏的更新即将来临:

RecyclerView将在不久的将来解决这个问题.正如http://www.grokkingandroid.com/first-glance-androids-recyclerview/所指出的,您将能够调用方法来准确指定更改,例如:

void notifyItemInserted(int position)
void notifyItemRemoved(int position)
void notifyItemChanged(int position)
Run Code Online (Sandbox Code Playgroud)

此外,每个人都希望使用基于RecyclerView的新视图,因为他们将获得漂亮的动画奖励!未来看起来很棒!:-)

  • 好东西!:)也许你可以在这里添加一个空检查 - 如果视图暂时不可用,则v可能为null.当然,如果用户滚动ListView,这些数据将会消失,因此还应该更新适配器中的数据(可能不调用notifyDataSetChanged()).一般来说,我认为将所有这些逻辑保留在适配器中是一个好主意,即将ListView引用传递给它. (3认同)
  • 我发布了解决方案.感谢您的信息! (2认同)

Ali*_*Ali 6

我就这样做了:

您的项目(行)必须具有唯一ID,以便稍后更新.当列表从适配器获取视图时,设置每个视图的标记.(如果在其他地方使用默认标签,您也可以使用密钥标签)

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    View view = super.getView(position, convertView, parent);
    view.setTag(getItemId(position));
    return view;
}
Run Code Online (Sandbox Code Playgroud)

对于更新检查列表的每个元素,如果具有给定id的视图在那里它是可见的,所以我们执行更新.

private void update(long id)
{

    int c = list.getChildCount();
    for (int i = 0; i < c; i++)
    {
        View view = list.getChildAt(i);
        if ((Long)view.getTag() == id)
        {
            // update view
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它实际上比其他方法更容易,当你处理id不是位置时更好!此外,您必须为可见的项目调用更新.