views:

63

answers:

1

The Problem:

  1. I have a local database (sqlite in this case) with each record representing an object instance of a particular class. For this example lets say I have a class called Product. In this case this is in the Android environment but I'm curious about standard Java as well.

  2. When an application or activity starts I read all the data from DB into volatile memory mostly for display to the user but sometimes the data is modified by the application or changes can be received from "the cloud" in a background process.

  3. Other applications/activities should be notified of any modifications to the database and update themselves and redisplay content as quickly as possible to prevent the user from seeing or modifying outdated Products.

My Proposed Solution:

A basic solution I am thinking of is that the DB is wrapped by a ContentProvider.

Each process has at most one in-memory object per record but there can be many pointers to this object. Calls to the ContentResolver will be wrapped in static methods and there will be a static WeakHashMap that stores all in-memory objects.

The ContentProvider sends a notification when a record is modified and all interested applications are listening using a ContentObserver. The ContentObserver refreshes the in-memory object in the WeakHashMap so that all references get the changes simultaneously.

The final step is to trigger a redisplay by calling an invalidate method on the appropriate Views or something like that. I haven't quite figured this part out yet but it's not as vital.

Your thoughts:

Is my proposed solution any good or am I way off the mark? Whats the best way to solve it in Android such that the user interface isn't out of sync or unresponsive? How would this be solved in desktop Java?

Thanks!

A: 

The ContentProvider is the way to go for android. Curious how you will distribute your apps though as you'll one and only one of them will have to have the service that does your 'background' stuff. Just a note though that since when passing objects through the Intent/Bundle/Parcelable system, the actual instance is not preserved. The original is deconstructed as defined by you and then transmitted to the other process via basic types. It is then reconstructed as a new instance to that class. It is impossible to share references as each Android app lives inside its own personal VM. Point being the WeakHashMap might be a bad idea (since the instant you add a new instance to it, you'll no longer have any references to it :) )

EDIT To keep things synced, you should make it so that the class you are persisting has wrapped all of it's set methods with a 'save()' method. (Basically setProp();save()). This way, when you set a property, you will also run an update() query on your content provider. This will update your database, cause the content observer to notice the change and refresh its data.

Moncader
Looks like the problem still remains, if I have two applications that read from the ContentProvider then I have two in memory objects. If application 1 updates it's object and sends it back to the content provider then application 2 has an object that is out of date. As for the WeakHashMap, that is only an intermediary that keeps all the references used by my application in one place. I would pass the objects along to the class that really wants to use the objects, that way when the caller is done with them that the WeakHashMap loses the reference and it is garbage collected properly.
satur9nine
As for the weakhashmap, it won't work because the references you store inside your service are in a different process than the classes uses 'them'. Remember, Android creates copies, it doesn't pass references through content providers. Give me a sec to update my answer for your other problem.
Moncader
I would have a WeakHashMap not in the service but one per application.
satur9nine