Android NotifyDataSetChanged()和对getView()的调用的计时

Android NotifyDataSetChanged()和对getView()的调用的计时,android,android-listview,Android,Android Listview,我正在调试一个带有ListView和两个线程的Android应用程序——一个更新数据存储的工作线程和一个主UI线程,该线程执行所有常见的视图操作,包括显示ListView。这应该是一个快速调试,所以我没有义务改变这个架构。我发现存在线程冲突,因为当getView试图使用数据存储中的内容时,工作线程有时正在运行 因此,为了防止这些冲突,我创建了一个计数为1的信号量,工作线程必须在接触数据存储阵列之前获取它。我还覆盖了notifyDataSetChanged,并在其中添加了一个获取和发布,以及一些日

我正在调试一个带有ListView和两个线程的Android应用程序——一个更新数据存储的工作线程和一个主UI线程,该线程执行所有常见的视图操作,包括显示ListView。这应该是一个快速调试,所以我没有义务改变这个架构。我发现存在线程冲突,因为当getView试图使用数据存储中的内容时,工作线程有时正在运行

因此,为了防止这些冲突,我创建了一个计数为1的信号量,工作线程必须在接触数据存储阵列之前获取它。我还覆盖了notifyDataSetChanged,并在其中添加了一个获取和发布,以及一些日志记录来检测它

@Override
  public void notifyDataSetChanged()  {

    try {
        MyActivity.datastoreSemaphore.acquire();
        Log.d ("notifyDataSetChanged()...",   " acquired semaphore " );  
        try {
            super.notifyDataSetChanged();
            Log.d ("notifyDataSetChanged()...",   "listItems.size()=" + String.valueOf(listItems.size()) + "  lv.getCount()=" + String.valueOf(lv.getCount()) );   //!! debugging
    } catch (Exception e) { 
            Log.e ("notifyDataSetChanged() inner catch ",   "Exception = " + e );   debugging   
        } finally {
            MyActivity.datastoreSemaphore.release();
            Log.d ("notifyDataSetChanged()...",   " released semaphore " );  
        }
     } catch (InterruptedException e) {
         Log.e ("notifyDataSetChanged() outer catch ",   "Exception = " + e ); 
     }                                  
 }
我还检测了getView,以下是我没有得到的:当调用notifyDataSetChanged时,跟踪显示在外部调用getView

05-25 13:36:37.865:D/notifyDataSetChanged…21863:acquired 信号量05-25 13:36:37.865:D/notifyDataSetChanged…21863: listItems.size=14 lv.getCount=14

05-25 13:36:37.865:D/notifyDataSetChanged…21863:released 信号量

05-25 13:36:37.869:D/进入getView…21863:position=0 适配器的getCount=14

05-25 13:36:37.873:D/在getView中…21863:listItems大小=14 位置=0

05-25 13:36:37.873:D/退出getView…21863:position=0 适配器的getCount=14

05-25 13:36:37.873:D/进入getView…21863:position=1 适配器的getCount=14

05-25 13:36:37.873:D/在getView中…21863:listItems大小=14 位置=1

换句话说,根据LogCat,我们称为notifyDataSetChanged;我们获取信号量,调用基本方法,从基本方法返回,释放信号量,然后getView循环开始

我的印象是,notifyDataSetChanged在整个getView循环完成之前不会返回,但这似乎是另一种说法。这里发生了什么事?注意,这个问题实际上不是关于信号量或线程配置的——我提到了那些提供上下文的配置——问题是关于getView循环WRT notifyDataSetChanged的计时

编辑:对notifyDataSetChanged的调用通过runOnUIThread中的runnable在主UI线程上运行。在屏幕上的跟踪中,所有适配器内容的TID显示为主UI线程。我将更新问题以反映这一点。

notifyDataSetChanged仅在其关联的观察者上激发onChanged方法

对于像ListView这样的AdapterView子类,这最终会调用requestLayout,而requestLayout是

因此,简而言之,这不是立即的。最终,将为每个项调用getView,但不是在notifyDataSetChanged完成之前

无论如何,从工作线程调用notifyDataSetChanged不是一个好主意。事实上,从后台线程修改适配器的内容可能会产生异常。信息通常是:

适配器的内容已更改,但ListView未收到 通知。确保适配器的内容未被修改 来自后台线程,但仅来自UI线程。确保你的 当其内容更改时,适配器调用notifyDataSetChanged


在我看来,通过确保在主线程上调用notifyDataSetChanged,您最好完全避免这个问题。您可以使用MainLoop上的处理程序从工作线程跳转到主线程。它在主线程上被调用-当我调用它时,我使用runOnUIThread中的runnable来执行。在屏幕上的跟踪中,所有适配器内容的TID显示为主UI线程。我将更新问题以反映这一点。我正在从runOnUIThread中的runnable调用notifyDataSetChanged。在屏幕上的跟踪中,所有适配器内容的TID显示为主UI线程。我已经更新了问题以反映这一点。@user316117。好吧,我还没明白。无论如何,答案都是一样的:notifyDataSetChanged不会立即调用getView。好的,我将把这个特定的问题计算为已回答的问题,并开始一个关于其含义的新问题