3

I have a List of items that I want in a ListView, and I can make it work with setting a custom adapter every time the List grows, but the program flow is kind of weird and I have problems with persistence. (If I switch tabs, the UI gets rebuilt with an empty ListView.)

Now, in my day job I'm a C# developer, so when I look at this problem I see a WPF ListView bound to an ObservableCollection. Does Android/Java have something like that, a "fire and forget" connection between a UI element and a data structure?

Dahud
  • 171
  • 1
  • 8

2 Answers2

2
  • You don't need to replace the adapter every time you change the data. The adapter "adapts" between data and view. There is no need to change the adapter as long as the way it adapts does not change.

  • Activity / Fragment lifecycle is not necessarily the lifecycle of your data collection. You can for example make a singleton data collection somewhere and use an adapter to display that collection all the time. Call .notifyDataSetChanged() on the adapter if you changed the data.

  • A persistent data collection in Android is probably best backed by a database. Take a look at LoaderManager & ContentProvider to provide and load data then displayed via CursorAdapter.

There is no automatic way of keeping a bunch of data available outside of your Activity / Fragment / .. lifecycle and it can get quite complicated but that's basically what you have to do if you want to keep data for longer than a given lifecycle. Singletons, Activity#onSaveInstanceState(), Activity#getLastNonConfigurationInstance(), Fragment#setRetainInstance(), ... are useful utilities to keep data in memory, databases are good for persistent data.

zapl
  • 63,179
  • 10
  • 123
  • 154
  • 2
    LocalBroadcasts and BroadcastReceiver would guarantee that only active components would get notifications. This components could refetch the data if needed. This would be a good way to work around the lifecycle problems. – schlingel Sep 10 '13 at 14:43
1

You have to do a little bit work yourself but it's possible. Use a ContentProvider as your DataSource. How the data is stored is up to you. I would prefer a SQLite-DB. A content provider has the possibility to add ContentObservers. (See this related question.)

You can write a CourserAdapter to fetch the Data from your content provider. And your ContentObserver should call notifyDataSetChanged() on your adapter. This closes the circle and your UI refreshes itself.

In Addition to zapls answer: You can also write an adapter which contains a BroadcastReceiver. When your DataSource changes you can send a LocalBroadcast. The broadcast handler just calls notifyDataSetChanged() of your adapter. I think this would work around most of the lifecycle problems because only active elements will get the broadcast.

The google documentation has an example for such a solution.

Community
  • 1
  • 1
schlingel
  • 8,560
  • 7
  • 34
  • 62
  • 1
    "ContentObserver should call notifyDataSetChanged() on your adapter" careful with that. Adapters re-load data in the UiThread and it's no longer recommended to notify the Adapter about changes. The `Loader` gets informed and re-loads async, then tells the Adapter about the new data. – zapl Sep 10 '13 at 15:02