android / codelab-android-datastore

Apache License 2.0
228 stars 105 forks source link

Lab refers to an undefined context.createDataStore(...) function #71

Open diegum opened 1 year ago

diegum commented 1 year ago

8. SharedPreferences to Proto DataStore is already very chaotic in terms of modifications that ain't clear whether they apply to UserPreferencesRepository.kt or to TasksActivity.kt or maybe to both.

That's because, in previous steps, the lab mandates to temporarily create a Context extension property userPreferencesStore that it's also temporarily injected from TasksActivity into UserPreferencesRepository.

But once at step 8. SharedPreferences to Proto DataStore, lots of these temporary things become finalized although the lab only tells what to edit but not where.

At some point, it requests to redefine userPreferencesStore but this time not as a Context extension property but as a presumably UserPreferencesRepository property. It doesn't clarify whose this redefinition belongs. I presume that it's UserPreferencesRepository.

It doesn't end there, though: the new definition invokes a non-existing context.createDataStore(...) function as follows:

private val userPreferencesStore: DataStore<UserPreferences> = context.createDataStore(
    fileName = "user_prefs.pb",
    serializer = UserPreferencesSerializer,
    migrations = listOf(sharedPrefsMigration)
)

I could only finish the lab by figuring out the missing extension function as follows:

fun <T> Context.createDataStore(
    fileName: String,
    serializer: Serializer<T>,
    corruptionHandler: ReplaceFileCorruptionHandler<T>? = null,
    migrations: List<DataMigration<T>> = listOf(),
    scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
): DataStore<T> =
    DataStoreFactory.create(
        produceFile = { File(this.filesDir, "datastore/$fileName") },
        serializer = serializer,
        corruptionHandler = corruptionHandler,
        migrations = migrations,
        scope = scope
    )

If my guessing is correct, the lab should include my guessed definition for God's sake.

The provided finished branch proto_datastore just stuck to the temporary definition (contradicting the lab instructions that called for a redefinition.)

Elaws commented 8 months ago

Agree, this tutorial needs to be completely cleaned and updated.

There are complete mismatches between the instructions & the code snippets in the instructions & the proto_datastore branch.

In TasksActivity, I just added (like they did in their proto_datastore branch) :

private val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(
    fileName = DATA_STORE_FILE_NAME,
    serializer = UserPreferencesSerializer,
    produceMigrations = {context ->
        listOf(SharedPreferencesMigration(
            context,
            USER_PREFERENCES_NAME
        ) { sharedPrefs: SharedPreferencesView, currentData: UserPreferences ->
            // Define the mapping from SharedPreferences to UserPreferences
            if (currentData.sortOrder == SortOrder.UNSPECIFIED) {
                currentData.toBuilder().setSortOrder(
                    SortOrder.valueOf(
                        sharedPrefs.getString(SORT_ORDER_KEY, SortOrder.NONE.name)!!
                    )
                ).build()
            } else {
                currentData
            }
        })
    }
)