检测BaseAdapter.notifyDataSetChanged()何时完成

36

我想知道BaseAdapter.notifyDataSetChanged()何时结束,并随后执行某些操作。我的代码:

BaseAdapter.notifyDataSetChanged();  
mScroller.startScroll(oldX, 0, dx, 0);

mScrollernotifyDataSetChanged()完成之前就已滚动,我希望在notifyDataSetChanged()完成后将mScroller滚动到oldX

请帮忙,谢谢。


11
请看这个问题。可能是重复的。 - grine4ka
也许 https://dev59.com/ZWYq5IYBdhLWcg3wcgPq#20997828 可以帮助你。 - Krunal Kapadiya
4个回答

11

与其扩展,BaseAdapter 支持注册一个 DataSetObserver,在那里您可以侦听 onChanged 事件。

notifyDataSetChanged 方法会触发此事件。

adapter.registerDataSetObserver(new DataSetObserver() {
    @Override
    public void onChanged() {
        // ...
    }
});

...

adapter.notifyDataSetChanged();

1
很不幸,onChanged() 方法被多次调用,而不仅仅是在视图布局完成时。 - PJ_Finnegan

2

我曾经遇到过完全相同的问题,尝试这个方法后对我非常有效。您需要重写方法notifyDataSetChanged(),在适配器类中完成此操作。只需复制我发布的代码,并将其中设置选择的行替换为您需要执行的任何操作即可。

@Override
public void notifyDataSetChanged()
{
    super.notifyDataSetChanged();

    parentGlobal.setSelection(this.getCount() - 1);  //This is how we start Activity fully scrolled to bottom
}

说了这么多,如果你想知道,“parentGlobal”是我在Activity中设置Adapter的ListView。在Adapter的构造函数中,我传入了ListView并将其设为“全局”的。如果“全局”不是Java术语,我很抱歉,因为我来自C++世界。

//放在Activity中:

lv_main = (ListView) findViewById(R.id.listView_conversation);
    adapter_main = new Adapter_Conversation(ConversationActivity.this, R.layout.layout_list_conversation,
            list_main_UI, lv_main, main_list_item_margin_px);
    lv_main.setAdapter(adapter_main);

//放在适配器中

public Adapter_Conversation(AppCompatActivity activity, @LayoutRes int resource,
                            ArrayList<Adapter_GetSet_Conversation> list_conversation, ListView lv_main,
                            int item_margin_px)

现在:'notifyDataSetChanged()'无法覆盖'androidx.recyclerview.widget.RecyclerView.Adapter'中的'notifyDataSetChanged()'; 被覆盖的方法是final。 - danyapd

1
请看下面使用 Kotlin 扩展函数的(更现代化的)实现:
fun <VH : ViewHolder> RecyclerView.Adapter<VH>.notifyDataSetChanged(
    completion: () -> Unit
) {
    val adapter = this
    val observer = object : RecyclerView.AdapterDataObserver() {
        override fun onChanged() {
            super.onChanged()
            adapter.unregisterAdapterDataObserver(this)
            completion.invoke()
        }
    }
    registerAdapterDataObserver(observer)
    notifyDataSetChanged()
}

-1

我曾经遇到过同样的问题,最终我做了这个-

 BaseAdapter.notifyDataSetChanged();  
 new Handler().postDelayed(new Runnable() {
      @Override
              public void run() {
                 mScroller.startScroll(oldX, 0, dx, 0);
                //write scroll code here
               }
       },50);  //scroll after 50ms

2
我以前也这样做,问题是它是基于时间驱动而不是事件驱动的,所以你必须猜测正确的时间,然后它很容易改变,这取决于运行它的设备,因为新设备可以比一些旧设备快得多。 - JamisonMan111
是的,有很多黑客技巧可以做到,而且不到1秒的动画时间并不太明显。 - karanatwal.github.io

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接