本文介绍了什么是最好的实践方式来更新适配器的基础数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行到一个IllegalStateException一个基本的列表更新到适配器(可能是一个ArrayAdapter或BaseAdapter的延伸,我不记得了)。我没有或记住异常,此刻的文字,但它说的东西到列表的内容变化的不适配的效果已被更改的通知。

该列表/可/从另一个线程比UI线程(主)其他更新。当我更新此列表(添加项目),我称之为notifyDataSetChanged。这个问题似乎是该适配器,或ListView连接到该适配器尝试自我更新调用此方法之前。如果发生这种情况,则抛出IllegalStateException。

如果我设置ListView的可见性,以更新前走了,然后再可见,不会发生错误。但是,这并不总是可行的。

我读的地方,你不能修改从另一个线程的底层这一点 - 这似乎限制了MVC模式,与这个特殊的名单,我想从不同的线程添加项目。我以为,只要我叫notifyDataSetChanged()我会很安全 - 适配器没有重温基础列表,直到这个方法被调用,但这似乎并没有这样的情况。

我想我问的是,是否可以安全地更新从线程比其他UI基础列表?此外,如果我想要一个适配器中修改数据,我修改了底层列表或适配器本身(通过add()等方法)。通过适配器修改数据似乎是错误的。

我碰到一个线程来从别人谁似乎有一个类似的问题,以我的另一个站点:http://osdir.com/ml/Android-Developers/2010-04/msg01199.html (这是从我抓起Visibility.GONE和。可见想法)。

为了让您更好地了解我的具体问题,我将描述了一下我是如何名单,适配器等进行设置。

我有一个包含一个链表对象指定的队列。队列扩展了观测,而当事情通过它的方法添加到其内部列表,我所说的setChanged()和notifyListeners()。此队列对象可以添加或删除任意数量的线程的项目。

我有一个单一的队列视图的活动,其中包含一个适配器。此次活动,在其的onCreate()方法,注册一个观察者监听到我的Queue对象。在观察者的update()方法,我称之为notifyDataSetChanged()上的适配器。

我加了很多日志输出,并确定在此IllegalStateExcption发生时,我的观察回调从来没有被调用。所以,就好像适配器注意到了名单的变化观察有机会通知其观察员,并调用我的方法,通知的内容发生了变化适配器之前。

所以,我想我所问的是,这是一个很好的方式来操纵式的适配器?这是一个问题,因为我是从一个线程比UI线程其他更新适配器的内容是什么?如果是这样的话,我可能心里有一个解决方案(给队列对象处理程序,以它创建时的UI线程,并使用该处理器的所有名单的修改,但这似乎不恰当)。

我意识到,这是一个非常开放的职位,但我有点失去了这一点,将AP preciate什么我写任何评论。

解决方案

这是行不通的。

MVC无关使用线程。

没有。其他线程可以(通过如后())触发更新到适配器,但更新自己必须在主应用程序线程上处理,对于当前连接的适配器到的ListView

您修改适配器通过适配器本身 ArrayAdapter 。你可以通过底层数据库/内容提供商的CursorAdapter 修改适配器。其他适配器可能会有所不同。

你有没有考虑过使用的LinkedBlockingQueue ,而不是实现自己的线程安全的队列

适配器应该叫 notifyDataSetChanged()对自己的(如果变化是由它们制成的)或者叫对他们的实体正在改变数据(例如,光标的CursorAdapter )。 的是MVC。该活动应该不知道,也不关心,当你的数据模型的改变。

可能你使用的是 ArrayAdapter ,在这种情况下,所有这些额外的观察者/通知东西是在你的方式,因为这是为您处理。你只需要安排更新 ArrayAdapter 主应用程序线程上。

没有什么特别,恕我直言。

如果你不强制更新返回到主应用程序线程,这样最终会崩溃,一旦你清楚你的其他问题。

您可以在您的附处理程序,或者你可以叫后() >的ListView 。

即兴,我想创建 ArrayAdapter ThreadSafeArrayAdapter 子类命名,并用它代替队列 ThreadSafeArrayAdapter 替换添加()插入(),和删除()与那些有超做它的事主应用程序线程上,通过处理程序后()

I'm running into an IllegalStateException updating an underlying List to an Adapter (might be an ArrayAdapter or an extension of BaseAdapter, I don't remember). I do not have or remember the text of the exception at the moment, but it says something to the effect of the List's content changing without the Adapter having been notified of the change.

This List /may/ be updated from another thread other than the UI thread (main). After I update this list (adding an item), I call notifyDataSetChanged. The issue seems to be that the Adapter, or ListView attached to the Adapter attempts to update itself before this method is invoked. When this happens, the IllegalStateException is thrown.

If I set the ListView's visibility to GONE before the update, then VISIBLE again, no error occurs. But this isn't always practical.

I read somewhere that you cannot modify the underlying this from another thread--this would seem to limit an MVC pattern, as with this particular List, I want to add items from different threads. I assumed that as long as I called notifyDataSetChanged() I'd be safe--that the Adapter didn't revisit the underlying List until this method was invoked but this doesn't seem to be the case.

I suppose what I'm asking is, can it be safe to update the underlying List from threads other than the UI? Additionally, if I want to modify the data within an Adapter, do I modify the underlying List or the Adapter itself (via its add(), etc. methods). Modifying the data through the Adapter seems wrong.

I came across a thread on another site from someone who seems to be having a similar problem to mine: http://osdir.com/ml/Android-Developers/2010-04/msg01199.html (this is from where I grabbed the Visibility.GONE and .VISIBLE idea).

To give you a better idea of my particular problem, I'll describe a bit of how my List, Adapter, etc. are set up.

I've an object named Queue that contains a LinkedList. Queue extends Observable, and when things are added to its internal list through its methods, I call setChanged() and notifyListeners(). This Queue object can have items added or removed from any number of threads.

I have a single "queue view" Activity that contains an Adapter. This Activity, in its onCreate() method, registers an Observer listener to my Queue object. In the Observer's update() method I call notifyDataSetChanged() on the Adapter.

I added a lot of log output and determined that when this IllegalStateExcption occurs that my Observer callback was never invoked. So it's as if the Adapter noticed the List's change before the Observer had a chance to notify its Observers, and call my method to notify the Adapter that the contents had changed.

So I suppose what I'm asking is, is this a good way to rig-up an Adapter? Is this a problem because I'm updating the Adapter's contents from a thread other than the UI thread? If this is the case, I may have a solution in mind (give the Queue object a Handler to the UI thread when it's created, and make all List modifications using that Handler, but this seems improper).

I realize that this is a very open-ended post, but I'm a bit lost on this and would appreciate any comments on what I've written.

解决方案

That won't work.

MVC has nothing to do with threads.

No. Other threads can trigger updates to the adapter (e.g., via post()), but the updates themselves must be processed on the main application thread, for an adapter that is currently attached to a ListView.

You modify your Adapter via the Adapter itself for ArrayAdapter. You modify your Adapter via the underlying database/content provider for CursorAdapter. Other adapters may vary.

Have you considered using LinkedBlockingQueue, rather than implementing your own thread-safe Queue?

Adapters should call notifyDataSetChanged() on themselves (if the change is made by them) or have it called on them by the entity that is changing the data (e.g., a Cursor for a CursorAdapter). That is MVC. The Activity should neither know nor care when your data model changes.

Possibly you are using an ArrayAdapter, in which case all this extra observer/notify stuff is getting in your way, since that's handled for you. You just need to arrange to update the ArrayAdapter on the main application thread.

Not particularly, IMHO.

If you aren't forcing the updates back to the main application thread, this will eventually crash, once you clear up your other problems.

You could use a Handler, or you could call post() on your attached ListView.

Off the cuff, I'd create a subclass of ArrayAdapter named ThreadSafeArrayAdapter and use it in place of Queue. ThreadSafeArrayAdapter replaces add(), insert(), and remove() with ones that have the superclass do its thing on the main application thread, via a Handler or post().

这篇关于什么是最好的实践方式来更新适配器的基础数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 13:04