class DataStoreManager(var context: Context) { // Create the dataStore and give it a name same as shared preferences private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("user_pref") val dataStore: DataStore<Preferences> = context.dataStore
// Create some keys we will use them to store and retrieve the data companion object { val USER_NAME_KEY = stringPreferencesKey("USER_NAME") val USER_AGE_KEY = intPreferencesKey("USER_AGE") }
// Store user data // refer to the data store and using edit
// store data as object suspend fun <T> storeObjectData(key: Preferences.Key<String>, value: T) { dataStore.edit { preferences -> preferences[key] = serializeData(value) } }
// save primitives data suspend fun storeStringData(key: Preferences.Key<String>, value: String) { dataStore.edit { preferences -> preferences[key] = value } }
suspend fun storeIntData(key: Preferences.Key<Int>, value: Int) { dataStore.edit { preferences -> preferences[key] = value } }
suspend fun storeDoubleData(key: Preferences.Key<Double>, value: Double) { dataStore.edit { preferences -> preferences[key] = value } }
suspend fun storeDoubleData(key: Preferences.Key<Float>, value: Float) { dataStore.edit { preferences -> preferences[key] = value } }
suspend fun storeLongData(key: Preferences.Key<Long>, value: Long) { dataStore.edit { preferences -> preferences[key] = value } }
suspend fun storeBooleanData(key: Preferences.Key<Boolean>, value: Boolean) { dataStore.edit { preferences -> preferences[key] = value } }
// Create a flow to retrieve data from the preferences // flow comes from the kotlin coroutine
// get data as object inline fun <reified T> getObjectData(key: Preferences.Key<String>): Flow<T> = dataStore.data.map { deSerializeData(it[key] ?: "") }
// get primitives data fun getStringData(key: Preferences.Key<String>): Flow<String> = dataStore.data.map { it[key] ?: "" }
Extension function for data communication in activity to activity
inline fun <reified T : Activity> Context.openActivity(vararg params: Pair<String, Any>) {
val intent = Intent(this, T::class.java)
intent.putExtras(*params)
this.startActivity(intent)
}
fun Intent.putExtras(vararg params: Pair<String, Any>): Intent {
if (params.isEmpty()) return this
params.forEach { (key, value) ->
when (value) {
is Int -> putExtra(key, value)
is Byte -> putExtra(key, value)
is Char -> putExtra(key, value)
is Long -> putExtra(key, value)
is Float -> putExtra(key, value)
is Short -> putExtra(key, value)
is Double -> putExtra(key, value)
is Boolean -> putExtra(key, value)
is Bundle -> putExtra(key, value)
is String -> putExtra(key, value)
is IntArray -> putExtra(key, value)
is ByteArray -> putExtra(key, value)
is CharArray -> putExtra(key, value)
is LongArray -> putExtra(key, value)
is FloatArray -> putExtra(key, value)
is Parcelable -> putExtra(key, value)
is ShortArray -> putExtra(key, value)
is DoubleArray -> putExtra(key, value)
is BooleanArray -> putExtra(key, value)
is CharSequence -> putExtra(key, value)
is Array<*> -> {
when {
value.isArrayOf<String>() ->
putExtra(key, value as Array<String?>)
value.isArrayOf<Parcelable>() ->
putExtra(key, value as Array<Parcelable?>)
value.isArrayOf<CharSequence>() ->
putExtra(key, value as Array<CharSequence?>)
else -> putExtra(key, value)
}
}
is java.io.Serializable -> putExtra(key, value)
}
}
return this
}
It was a nightmare working with viewPager when had to handle fragmentPagerAdapter. But in terms of viewPager2 its just fun. Cause we can easily use recyclerview adapter in ViewPager2. I have just done a demo project with custom indicator for viewPager2 with recyclerView Adapter. Let’s start coding step by step.