Closed kamilwlf closed 9 years ago
To share data between two processes you need inter-process communication (IPC).
A common android example for this are SyncAdapters
which run on different processes than your UI. When you want to trigger an action in the UI from your SyncAdapter
you can't simply call a function of your activity you need to use IPC. When you use the SharedPreferences
in the SyncAdapter you are able to save the data. But the UI (in a different process) uses a different SharedPreferences
object and does not receive a data change. Even worse, if you read the value written in the SyncAdapter
from the UI process you get the old value for some seconds. (issue on StackOverflow)
Implementing Binder
for IPC is hard and low level. But ContentProviders
do IPC out of the box. That's why a ContentProvider
is used to support multiple processes.
A ContentProvider
doesn't mean the data is written to a database. It's just a interface which supports CRUD operations. And those operations are process save. Yes, Tray is using a sqlite database under the hood but if would be possible to swap out this implementation and save the data to any other persistence framework. This works because the ContentProvider
would use the same persistence Object for all operations. But the multi process support would only be guaranteed when you access the data with Tray and the ContentProvider
and not directly with the other persistence frameworks.
So ContentProviders
makes CRUD operations multi process save.
The Sqlite database is used to store the data. It's no just a simple key value store (like the shared preferences) because you can get additional informations for every key value pair saved to Tray automatically. You can get informations when the data was saved first or when the data was last updated. (see here).
ContentProvider
used is only accessible from your Application.getContext().getContentResolver().insert(uri, values);
. This means Tray is just a high level abstraction to access the data in the ContentProvider
.Tray doesn't support asynchronous operations. Everything runs synchronous. A mPrefs.put("key", "data");
immediately writes the data into the database. If this function returns the data is saved to disk.
It's up to the developer where to save the data, inside the UI Thread or in a worker thread. In my cases this was never a problem because I was writing data in a non-UI process where I didn't have to care about frames.
I hope I could help you understand this lib :smile:!
so now everything is clear.
I propose to describe(copy your text) it on the main page or in the documentation
I have a question,when a call mPrefs.get("key") on the ui thread, and it is synchronous, will it block the UI thread when the data is so big?
Support use across multiple processess
I'm trying to understand how can I take advantage of it . Can you give a practical example ?
Is it simply writes data asynchronous?
what will be happen when the app is killed before the data has been written to disk? Is it true 'commit' semantics?
Topics that do not fully understand:
Tray solves this problem with a ContentProvider based storage.
What are the benefits it gives to us? Why we want use ContentProvider? Whether it's sharing of resources between different applications ?
Works multiprocess
So I can save several values in parallel?
automatically saves metadata for each entry (created, last updated, ...)
I do not understand? automatically saves metadata?
At first, it was the simpst way to use IPC with Binder to solve the multiprocess problem. Using the ContentProvider with a database turned out to be very handy when it comes to save metadata. We thought about replacing the database with the real SharedPreferences to boost the performance (the SharedPreferences do not access the disk for every read/write action which causes the multiprocess problem btw) but the metadata seemed to be more valuable to us.
Why we want use ContentProvider? Whether it's sharing of resources between different applications ?