https://unsplash.com/@petrebels

Wanna use Jetpack DataStore?

Randy Arba
4 min readAug 3, 2022

--

I have a bad experience using SharePreference because got crashed after revamping the feature. The root cause is the scheme of string JSON is not valid and fails to parse (Runtime Exception), actually my SharedPreferences save object data and format it into string JSON using Google Gson so it can be stored in string type, but when revamp I change model data and entity. My mistake is not to check the old data structure/scheme so it triggers a crash that loads the old scheme and does not match with the new scheme. Even those repositories of responsibility load local data not being added try and catch with a default value.

Therefore I try to use try and catch for loading local data if there is an error parse trigger, but I think there is still a part that needs to improve about this approach. because our current repository already uses Rxjava/RxKotlin we can make it observable to handle errors, but I think it needs to take effort and must have another abstraction or bridge helper to this. This idea not only supports error handling but also gives some long-running task processing on observable that can be supported by Rxjava/RxKotlin. Another walk-around is using third parties library, such as Jetpack DataStore.

Cons SharedPreferences

  • Unfortunately yeah I already mention before, Synchronous work, SharedPreferences runs its read/write operations, except apply() function, on the main thread. because of this disadvantage,
  • Blocking the UI thread when making calls or inconsistent, persisted data throughout your app.
  • Error Handling SharedPreferences throw parsing errors as runtime exceptions, making the app vulnerable to trigger crashes.
  • None type safety and data consistency, Using key-value for saving and retrieving data doesn’t provide type safety protection.

Jetpack DataStore lib,

DataStore is a library from google that store key-value pairs or type object that concurent(Rx and coroutine) running and support protocol buffer. You must be already using shared preferences on Android and the behavior is same, but some of pitfalls of Shared Preferences will covered with DataStore.

There is another alternative for simple store key value such as Paper it also support on RxJava/RxKotlin. but when we compare those library still, the library is lack support or maintenance, Based on my experience using Paper library, it is awesome and can mix with RxJava support not only that Paper also supports not only primitive data support but also support data class object. So I would recommend a library from Google officials like jetpack datastore that long term support.

With the usage of SharedPreferencesMigration we have the opportunity to migrate SharedPrefrences to DataStore. Related article on this topic: Working with Preferences DataStore - Codelabs.

Pros Data Store

  • Preferences DataStore. (DataStore is safe to call on the UI thread because it uses Dispatchers.IO under the hood) Non-blocking UI thread DataStore was built to address all of these issues.
  • However, with Proto DataStore, you can predefine a schema for your data model and get the additional benefit of full type safety.
  • Safe runtime exception.
  • Has transaction API that strong consistency guarantees
  • Handle data migration

Cons Data Store

  • if you concern about security and encryption current data store is not provided yet, but from the issue tracker, they got high priority because many people still consider encryption for the data store before the migration happens so stay tuned and hope they will add ASAP. Perhaps you can implement the same way as EncryptedSharedPreferences
  • DataStore requires a lot of boilerplate. 100+ lines of code in UserPreferencesRepository for two preferences. Adding Another preference would require changing code, in many different places at least four. This is just another opinion for a person who implements this approach because I believe people will handle and implement it in a different way.

What if, you still use SharePreferences?

If you insist on using shared Preferences and not using DataStore because still does not fit with your criteria maybe there are alternative approaches, which better and easier to scale:

  • Add Kotlin delegates (You can use your own or use another used library). The result is type-safe and concise: each property declaration with a default value. Great for most cases, support thread-safe, but it did not provides some transactional guarantees or support complex/custom data types without an extra step.
  • This step is already mention above, using RxJava or Stateflow holding a data class, plus a coroutine that observes it in the background and saves to disk as JSON string in vice versa you can load again using serialize provider like Google GSON. If you feel bored using GSON maybe another walk around using specialized Persista, Support custom data types & subscribing to updates every transaction.

Please comment below if you have another opinion or experience about datastore implementation. Hope we can discuss it there. Thanks all. :D

--

--