NotifyDataSetChanged()和getView呼叫的定时() [英] Timing of NotifyDataSetChanged() and calls to getView()

查看:155
本文介绍了NotifyDataSetChanged()和getView呼叫的定时()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我调试与ListView和2个线程Android应用程序 - 一个工作线程,更新数据存储和做所有通常的看法的东西,包括显示列表视图主UI线程。 (这应该是一个快速的调试,所以我的任务不是改变这一点,架构)。我发现有一个线程冲突,因为工作线程有时运转时的 getView()的试图在数据存储消耗的东西。

I'm debugging an Android app with ListView and 2 threads - a worker thread that updates the datastore and the main UI thread that does all the usual View stuff including displaying the listview. (this is supposed to be a quick debug so I'm not mandated to change this that architecture). I found that there was a thread collision because the worker thread was sometimes running when getView() was trying to consume stuff in the datastore.

所以要prevent这些碰撞我创建了一个信号量为1的计数和工作线程都有接触数据存储阵列之前获取它。我也推翻的 notifyDataSetChanged()的,把一个AQUIRE并在它释放以及一些测井仪器它。

So to prevent these collisions I create a semaphore with a count of 1 and the worker thread has to acquire it before touching the datastore arrays. I also overrode notifyDataSetChanged() and put an aquire and release in it as well as some logging to instrument it.

@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()的被外界称为时的 notifyDataSetChanged()的被称为..。 。

I also instrumented getView() and here's what I don't get: The trace shows getView() being called OUTSIDE of when notifyDataSetChanged() is called.. . .

13 05-25:/ notifyDataSetChanged()...(21863)D:收购36:37.865
  信号灯05-25 13:36:37.865:D / notifyDataSetChanged()...(21863):
  listItems.size()= 14 lv.getCount()= 14

05-25 13:36:37.865: D/notifyDataSetChanged()...(21863): acquired semaphore 05-25 13:36:37.865: D/notifyDataSetChanged()...(21863): listItems.size()=14 lv.getCount()=14

13 05-25:36:37.865:D / notifyDataSetChanged()...(21863):公布
  信号灯

05-25 13:36:37.865: D/notifyDataSetChanged()...(21863): released semaphore

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

05-25 13:36:37.869: D/Entering getView() ...(21863): position=0 Adapter's getCount()=14

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

05-25 13:36:37.873: D/in getView() ...(21863): listItems size =14 position = 0

13 05-25:36:37.873:D /退出getView()...(21863):位置= 0
  适配器的getCount将()= 14

05-25 13:36:37.873: D/Exiting getView() ...(21863): position=0 Adapter's getCount()=14

13 05-25:36:37.873:D /进入getView()...(21863):位置= 1
  适配器的getCount将()= 14

05-25 13:36:37.873: D/Entering getView() ...(21863): position=1 Adapter's getCount()=14

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

05-25 13:36:37.873: D/in getView() ...(21863): listItems size =14 position = 1

在换句话说,根据LogCat中,我们调用的 notifyDataSetChanged()的;我们AQUIRE信号量,调用基方法,从基本方法的返回,释放信号量,和然后 getView()的循环开始。 。

In other words, according to LogCat, we call notifyDataSetChanged(); we aquire the semaphore, call the base method, return from the base method, release the semaphore, and THEN the getView() loop starts . . .

我是IM pression的 notifyDataSetChanged()的不返回,直到整个的 getView()的环路的事情做下,但是这似乎说除此以外。这里发生了什么? ( NB ,这个问题是不是真的对信号或线程collsions - 我提到的那些来提供上下文 - 问题是关于 getView()的时机的循环WRT的 notifyDataSetChanged()的。)

I was under the impression that notifyDataSetChanged() doesn't return until the whole getView() loop thing is done, but this seems to say otherwise. What's happening here? (N.B., this question isn't really about the semaphore or thread collsions - I mentioned those to provide context - the question is about the timing of the getView() loop WRT notifyDataSetChanged() .)

编辑:的调用的 notifyDataSetChanged()的在主UI线程上通过一个可运行在runOnUIThread的run()。在屏幕上跟踪的TID的所有适配器的东西被证明是在主UI线程。我会更新的问题,以反映这一点。

the calls to notifyDataSetChanged() are run on the main UI thread via a runnable in runOnUIThread(). In the trace on the screen the TID for all the adapter stuff is shown to be the main UI thread. I'll update the Question to reflect this.

推荐答案

notifyDataSetChanged()只触发调用onChanged()对与其相关的观测方法。

notifyDataSetChanged() only fires the onChanged() method on its associated observers.

有关适配器视图的子类(如的ListView ),这结束调用 requestLayout( ),其中 时间表布局传球视图树的。

For AdapterView subclasses (such as ListView), this ends up calling requestLayout(), which schedules a layout pass of the view tree.

因此​​,简而言之,它不是立竿见影的。最后, getView()将被调用为每个项目,而不是之前 notifyDataSetChanged()已完成

So, in short, it's not immediate. Eventually, getView() will be called for each item, but not before notifyDataSetChanged() has finished.

不管怎样,调用 notifyDataSetChanged()从工作线程是不是一个好主意。事实上,从后台线程修改适配器的内容是可能产生一个例外。该消息通常是:

Anyway, calling notifyDataSetChanged() from a worker thread is not a good idea. In fact, modifying an Adapter's contents from a background thread is likely to produce an exception. The message usually is:

适配器的内容发生了变化,但ListView控件没有收到
  通知。确保我们的适配器的内容不被修改
  从后台线程,但只能从UI线程。确保您的
  适配器调用notifyDataSetChanged()时,其含量的变化。

The content of the adapter has changed but ListView did not receive a notification. Make sure the content of our adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.

这篇关于NotifyDataSetChanged()和getView呼叫的定时()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆