NotifyDataSetChanged()的时间和对getView()的调用

时间:2014-05-26 18:26:31

标签: android android-listview

我正在使用ListView和2个线程调试Android应用程序 - 一个更新数据存储区的工作线程和执行所有常见View内容的主UI线程,包括显示列表视图。 (这应该是一个快速调试,所以我没有被要求改变这个架构)。我发现存在线程冲突,因为当 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()这里是我得不到的东西:跟踪显示 getView()被称为OUTSIDE的时候 notifyDataSetChanged()被调用.. 。

  

05-25 13:36:37.865:D / notifyDataSetChanged()...(21863):获得   信号量05-25 13:36:37.865:D / notifyDataSetChanged()...(21863):   listItems.size()= 14 lv.getCount()= 14

     

05-25 13:36:37.865:D / notifyDataSetChanged()...(21863):已发布   信号量

     

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

     

05-25 13:36:37.873:D / in getView()...(21863):listItems size = 14   position = 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 / in getView()...(21863):listItems size = 14   position = 1

换句话说,根据LogCat,我们调用 notifyDataSetChanged();我们获取信号量,调用基本方法,从基本方法返回,释放信号量,那么 getView()循环启动。 。

我的印象是 notifyDataSetChanged()在整个 getView()循环事件完成之前不会返回,但这似乎不是这样。这里发生了什么事? ( NB ,这个问题并不是关于信号量或线程collsions - 我提到那些提供上下文 - 问题是关于 getView()循环WRT的时间 notifyDataSetChanged()。)

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

1 个答案:

答案 0 :(得分:0)

notifyDataSetChanged()仅在其关联的观察者上触发onChanged()方法。

对于AdapterView子类(例如ListView),最终会调用requestLayout() schedules a layout pass of the view tree

因此,简而言之,它不是即时的。最终,将为每个项目调用getView(),但在notifyDataSetChanged()完成之前不会。{/ p>

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

  

适配器的内容已更改,但ListView未收到   通知。确保未修改适配器的内容   来自后台线程,但仅来自UI线程。确保你的   适配器在其内容发生变化时调用notifyDataSetChanged()。