`listView.invalidate()`和`adapter.notifyDataHasChanged()`之间有区别吗?

时间:2015-01-12 23:59:54

标签: java android listview contextmenu adapter

我有一个项目列表。

我想长时间删除一个项目。

我看到这篇文章,它对我有用。

出于好奇,我想知道为什么其他解决方案对我不起作用:

sol 1

我将列表注册到上下文菜单:

registerForContextMenu(listView);

然后:

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    if (v.getId()==R.id.comments_list) {
        MenuInflater inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.phone_list_contextual_menu, menu);
    }
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    switch(item.getItemId()) {
        case R.id.edit: {
           return true;
        }
        case R.id.delete: {
            comments.remove(info.id);
            listView.invalidate();
            return true;
        }
        default: {
            return super.onContextItemSelected(item);
        }
    }
}

之间有区别吗?

listView.invalidate()adapter.notifyDataHasChanged()?在电话会议旁边?

为了让删除工作,我错过了什么?

sol 2

listView.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        int position = (int) v.getTag();
        comments.remove(position);
        listView.invalidate();
        return true;
    }
});

而不是

  listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){
        @Override
        public boolean onItemLongClick(AdapterView<?> av, View v, int pos, long id) {
            comments.remove(pos);
            //listView.invalidate();
            arrayAdapter.notifyDataSetChanged();
            return true;
        }
    });

我理解setOnItemLongClickListenersetOnLongClickListener更适合我的需要,但还是

为什么这对我不起作用?

2 个答案:

答案 0 :(得分:1)

不同之处在于invalidate会导致列表中的所有视图被废弃并重新绘制。注意我说的是视图,这就是你在屏幕上实际看到的内容(例如,你可以在屏幕上看到3个视图,但列表中有20个视图)

另一方面,

notifyDataHasChanged告诉适配器内容已更改,适配器需要在内容上重新运行其方法以刷新列表。

您几乎总是希望使用notifyDataHasChanged,但这完全取决于您要完成的工作。

希望有所帮助。

答案 1 :(得分:1)

  

之间有区别吗?      

listView.invalidate()和adapter.notifyDataHasChanged()?在电话会议旁边?

据我所知,adapter.notifyDataHasChanged()将执行listView.invalidate()以及更多操作。这意味着它还将包括项目数量的变化,并可能通知其他观察者数据变化。相关代码在这里:

http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/widget/AdapterView.java#798

这适用于notifyDataHasChanged(),因为您可以看到mItemCount是使用新值进行的。这意味着如果向arrayadapter添加更多项目,则invalidate或更好的invalidateViews将不会显示它们,至少在列表末尾。我注意到的一件事是上面的代码没有无效的调用 - 可能是通过其他一些方法调用的。

以下是invalidateViews的源代码(我认为比Invalidate更合适):<​​/ p>

http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/widget/AbsListView.java#5078

它没有更新项目计数的代码。

如果你搜索android源代码的源代码,你会发现只有少数情况下调用invalidateViews,其中一些是优化黑客。