does anybody have any elegant solution for refreshing the Views
in Fragments
in a FragmentActivity's
ViewPager
after a sync Service
from a SyncAdapter
runs?
I've tried calling notifyDataSetChanged()
and notifyDataSetInvalidated()
on my adapter, as well as refreshDrawableState()
on my views (GridViews
), but to no avail. Perhaps I've been calling them from the wrong places -- I've tried doing it at setUserVisibleHint
where isVisible
=true, hoping to trigger it whenever the fragment comes into view, but it doesn't work.
I've also been using ASync calls to the SQLite database for my data needs, rather than a Content Provider
, which I think would have made this a bit easier. I can think of a couple of ways to do it without a Content Provider
, but neither are very nice.
Any ideas? I can provide code if wished. Thanks.
I'll assume that you're using an AsyncTask for loading the cursor just for the sake of the explanation, but it would work the same if you're using a Loader, an ThreadPool or whatever.
From the service, as soon as new data was changed I would send a
LocalBroadcast
. The activity might be there or not, so a broadcast is a good way to let it know there's new data. So from the service you would do:and then from the activity/fragment that have the Cursor, you'll be listening to this broadcast like this:
as I said, this next part varies depending on what threading method you're using to load the Cursor, for this example I'll show in a AsyncTask because it's very popular (but I really believe you and every developer in the world should use the Loaders pattern).
}
The above approach I tested and used before and I know it works. There's a way of making it work with the flag
FLAG_REGISTER_CONTENT_OBSERVER
and overrideonContentChanged()
to re-execute the query and swap the cursor, but I've never tested it. It will be something like that:init your adapter with the constructor
CursorAdapter(Context context, Cursor c, int flags)
passing the flagFLAG_REGISTER_CONTENT_OBSERVER
and overrideonContentChanged()
. Inside onContentChanged you will execute the AsyncTask just like above. This way you don't have to use theLocalBroadcastManager
as the database will alert. The reason that method is not my main answer, it's because I've never tested it.Note that
autoRequery
have been deprecated and it's discouraged as it performs data loading in the UI thread.edit:
I just noticed that the content observer is an API 11 thing. You have two options: 1 use the support library instead: https://developer.android.com/reference/android/support/v4/widget/CursorAdapter.html or the broadcast option.
Register a
BroadcastReceiver
in the fragments you have and in itsonReceive
callrefresh
- this method is supposed to update the UI depending what you have inside. For making your code easy to use, have a baseFragment
class and do the registering/unregistering there along with an abstractrefresh
method that will be implemented by children fragments. Something like:In your
Service
, when your work is done, broadcast an intent with above action. So if there are fragments to show updated data, their receiver will be notified and that will callrefresh
ON EACH FRAGMENT. Something like from your service:The advantage is that you don't need to care when the fragment is shown or not since the receiver is there for the life-time of your fragment's view.
Recreate your adapter from scratch with the new data, and reassign it to the ListView (or whatever Views you have).