Friday, June 11, 2010

Re: [android-developers] Re: Using a ListView and an Adapter: How to use notifyDataSetChanged()?

Hey Streets,

thanks.

Actually I already run this on the UI thread.

Here is my code (from a ListActivity):

        updateCursorRunnable = new Runnable() {
            public void run() {
                updateCursor();
                refreshUI();
            }
        };

  Above you see the Runnable that later on will be executed on the UI thread.

  Here are the implementations: (I didn't cut anything out this time, maybe I making in error in the "unimportant" stuff. If you see something else that needs improving, like the changing of cursors, let me know.).

   private boolean updateCursor() {
        boolean cursorChanged = false;

        if (dbQuery.hasChanged()) {
            final Cursor oldCursor = listAdapter.getCursor();
            if (oldCursor != null)
                stopManagingCursor(oldCursor);

            final Cursor cursor = getEntryManager().getContentCursor(dbQuery);
            startManagingCursor(cursor);
            listAdapter.changeCursor(cursor);
            // listAdapter.notifyDataSetChanged();
            cursorChanged = true;

        } else {
            Timing t = null;
            if (NewsRob.isDebuggingEnabled(this))
                t = new Timing("ArticleListActivity::requery", this);
            // listAdapter.notifyDataSetChanged(); doesn't work. use requery
            // instead
            listAdapter.getCursor().requery();    <------ That's what I mean. Would prefer notifyDataSetChanged.

            if (t != null)
                t.stop();
        }
        return cursorChanged;
    }

    void refreshUI() {
        ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
        updateButtons();
        updateControlPanelTitle();
        refreshProgressBar();
        if (getListAdapter().getCount() == 0 && !isTaskRoot())
            finish();
    }

And the Runnable is triggered like this:

 @Override
    public void modelUpdated() {
        Timing t = new Timing("modelUpdated()", this);
        runOnUiThread(updateCursorRunnable);
        t.stop();
    }

  Any ideas?

Cheers,
Mariano

On Fri, Jun 11, 2010 at 4:21 PM, Streets Of Boston <flyingdutchie@gmail.com> wrote:
I don't know your code, but it looks like the notifiyDataSetChanged()
(like many other methods that can update the UI) needs to be called on
the main GUI thread.

You need to get hold of a View or a Hander (that was created on the
main GUI thread, e.g. in your onCreate()) and call 'post' on it:

// the code is executed by your background thread
... do stuff ...
...
// communicate that the list needs updating
viewOrHandler.post(new Runnable() {
 public void run() {
   myListAdapter.notifyDataSetChanged();
 }
});
...


On Jun 3, 2:55 pm, Mariano Kamp <mariano.k...@gmail.com> wrote:
> Hi.
>
> Just watched Google IO's "World Of ListView" presentation [1]. Awesome
> stuff. I think every Android dev should watch it.
>
> One gotcha for me was to use BaseAdapter.notifyDataSetChanged[2]. I checked
> code that I have written more than a year ago and found that I did try to
> use that, but commented it out with '// doesn't work' and I use requery()
> instead. That is of course much slower.
>
> I now tried to find out why I wrote that it didn't work and hoped that I am
> meanwhile so much wiser that it would be easier to understand the proper use
> of the API. So much for ambition:  The effect I see is that the list is not
> updated after I call notifyDataSetChanged(), but works with requery() and I
> am not so much wiser ;-(
>
> What could be the issue here? I use a ResourceCursorAdapter and only
> implemented the bindView() Method. This method is called when I call
> notifyDataSetChanged() on the RCAdapter. However the method is called with a
> cursor that contains the stale data.
>
> Now there was a second gotcha from the presentation that I couldn't really
> place. It was said that the data should be committed on the GUI thread too
> (before calling notifyDataSetChanged()). I couldn't place it then, but I now
> suspect that this may be the issue here. So the rule would be to do the
> commit() on the Cursor on the UI thread?
> I do the updates to the database using a Service. This Service runs in the
> background, sometimes the app is in the foreground at the same time, but
> most often not. So I don't see how I should commit something in a UI thread?
> Is this the issue here? There are two different Cursors and I could only use
> notifyDataSetChanged when it would be the same cursor, otherwise requery()
> is correct?
>
> Is that it? Any ideas?
>
> Is somebody going to write a book "The Android SDK - The missing manual"?
> ;-)
>
> Cheers,
> Mariano
>
> [1]http://code.google.com/events/io/2010/sessions/world-of-listview-andr...
> [2]http://developer.android.com/reference/android/widget/BaseAdapter.htm...()

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment