DataStore & Preferences Quiz

DATA › Storage

Which statement about SharedPreferences.apply() is correct?

Answer: It updates memory immediately and writes to disk asynchronously, returning void

apply() commits the change to the in-memory map right away and schedules the disk write in the background, returning void. commit() is the synchronous variant that returns a Boolean.

What is the key advantage of Proto DataStore over Preferences DataStore?

Answer: It uses a defined schema to provide compile-time type safety

Proto DataStore uses a .proto schema to generate typed classes, giving compile-time type safety. Preferences DataStore is untyped key-value like SharedPreferences.

How are reads exposed in DataStore?

Answer: As a Flow<T> via the data property

DataStore exposes its data as a Flow<T> (dataStore.data), enabling asynchronous, reactive, non-blocking reads. Writes are suspend functions.

Which class is used to migrate existing SharedPreferences data into DataStore?

Answer: SharedPreferencesMigration

SharedPreferencesMigration is supplied in the migrations list when building the DataStore; it copies values across on first access and then removes the original SharedPreferences file by default.

What does the suspend dataStore.edit { } block guarantee for Preferences DataStore?

Answer: It runs the block as a single atomic transaction

The edit block executes as a single atomic, transactional update; all changes are applied and persisted together, preserving read-after-write consistency.

What is the current recommendation regarding EncryptedSharedPreferences in modern Android?

Answer: It is deprecated and not the recommended choice for new code

EncryptedSharedPreferences from androidx.security:security-crypto is deprecated. Google now advises relying on platform disk encryption plus the Keystore or maintained crypto libraries instead.

If a DataStore file becomes corrupted, what is the correct way to recover gracefully?

Answer: Pass a ReplaceFileCorruptionHandler when building the DataStore

A corrupted file causes a CorruptionException; supplying a ReplaceFileCorruptionHandler lets DataStore replace the bad file with a default value rather than crashing.

What is the recommended way to obtain a Preferences DataStore instance in modern Android?

Answer: Use the preferencesDataStore delegate once at a file’s top level

The preferencesDataStore delegate creates and caches a single DataStore for a given file name, which is the recommended pattern; building new instances per call risks violating the one-instance-per-file rule.

What happens if you create two DataStore instances backed by the same file within one process?

Answer: The second creation throws an IllegalStateException

DataStore enforces a single active instance per file per process to guarantee atomicity and read-after-write consistency; a second instance for the same file throws IllegalStateException.

When setting up a Proto DataStore, what must you supply so it can convert your object to and from bytes on disk?

Answer: A Serializer<T> implementation

Proto DataStore requires a Serializer<T> that defines the default value and how to read/write the type as bytes; this is what gives Proto DataStore its typed, schema-backed persistence.

How do you write a new value to a Proto DataStore?

Answer: Call the suspend updateData { current -> ... } function

Proto DataStore writes go through the suspend updateData function, which receives the current value and returns the updated one as a single atomic transaction. edit { } is the Preferences DataStore API.

Which expression correctly creates a key for storing an Int in Preferences DataStore today?

Answer: intPreferencesKey("count")

intPreferencesKey(name) is the current typed-key helper for ints (alongside stringPreferencesKey, booleanPreferencesKey, etc.). The generic preferencesKey<Int>() form was removed in favor of these type-specific factories.

While collecting dataStore.data, an IOException can be thrown if the file cannot be read. What is the idiomatic way to handle it?

Answer: Use Flow's catch operator to emit emptyPreferences()

Read errors surface through the Flow, so the idiomatic fix is the catch operator: on an IOException you emit emptyPreferences() (or a default), while rethrowing other exceptions you can't recover from.

Which scenario is DataStore NOT designed to handle well?

Answer: Large, complex, or relational datasets that need querying

DataStore is for small/simple datasets and rewrites the whole file on each write; large, complex, or queryable relational data should use Room instead.

Back to DataStore & Preferences