@@ -29,6 +29,7 @@ import kotlin.reflect.typeOf
2929 * @param T the class of data
3030 * @param dataSaverInterface the interface to read/save data, see [DataSaverInterface]
3131 * @param key persistence key
32+ * @param typeConverter ITypeConverter? specific type converter for this state, the priority is higher than the global one
3233 * @param initialValue NOTE: YOU SHOULD READ THE SAVED VALUE AND PASSED IT AS THIS PARAMETER BY YOURSELF(see: [mutableDataSaverStateOf])
3334 * @param savePolicy how and when to save data, see [SavePolicy]
3435 * @param async Boolean whether to save data asynchronously
@@ -39,6 +40,7 @@ class DataSaverMutableState<T>(
3940 private val dataSaverInterface : DataSaverInterface ,
4041 private val key : String ,
4142 private val initialValue : T ,
43+ private val typeConverter : ITypeConverter ? = null ,
4244 private val savePolicy : SavePolicy = SavePolicy .IMMEDIATELY ,
4345 private val async : Boolean = false ,
4446 private val coroutineScope : CoroutineScope ? = null
@@ -56,21 +58,6 @@ class DataSaverMutableState<T>(
5658 doSetValue(value)
5759 }
5860
59- @Deprecated(
60- " 请优先使用带`savePolicy`参数的构造函数(The constructor with parameter `savePolicy` is preferred.)" ,
61- )
62- constructor (
63- dataSaverInterface: DataSaverInterface ,
64- key: String ,
65- value: T ,
66- autoSave: Boolean = true ,
67- ) : this (
68- dataSaverInterface,
69- key,
70- value,
71- if (autoSave) SavePolicy .IMMEDIATELY else SavePolicy .NEVER
72- )
73-
7461 operator fun setValue (thisObj : Any? , property : KProperty <* >, value : T ) {
7562 doSetValue(value)
7663 }
@@ -92,7 +79,7 @@ class DataSaverMutableState<T>(
9279 if (async) {
9380 job?.cancel()
9481 job = scope.launch {
95- val typeConverter = findSaver(value)
82+ val typeConverter = typeConverter?.asSaver(value) ? : findSaver(value)
9683 if (typeConverter != null ) {
9784 val convertedData = typeConverter(value)
9885 log(" saveConvertedData(async: $async ): $key -> $value (as $convertedData )" )
@@ -103,7 +90,7 @@ class DataSaverMutableState<T>(
10390 }
10491 }
10592 } else {
106- val typeConverter = findSaver(value)
93+ val typeConverter = typeConverter?.asSaver(value) ? : findSaver(value)
10794 if (typeConverter != null ) {
10895 val convertedData = typeConverter(value)
10996 log(" saveConvertedData(async: $async ): $key -> $value (as $convertedData )" )
@@ -172,6 +159,7 @@ class DataSaverMutableState<T>(
172159 *
173160 * @param key String
174161 * @param initialValue T default value if it is initialized the first time
162+ * @param typeConverter ITypeConverter? specific type converter for this state, the priority is higher than the global one
175163 * @param savePolicy how and when to save data, see [SavePolicy]
176164 * @param async whether to save data asynchronously
177165 * @param senseExternalDataChange whether to sense external data change, default to false. To use this, your [DataSaverInterface.senseExternalDataChange] must be true as well.
@@ -184,13 +172,20 @@ class DataSaverMutableState<T>(
184172inline fun <reified T > rememberDataSaverState (
185173 key : String ,
186174 initialValue : T ,
175+ typeConverter : ITypeConverter ? = null,
187176 savePolicy : SavePolicy = SavePolicy .IMMEDIATELY ,
188177 async : Boolean = true,
189178 senseExternalDataChange : Boolean = false,
190179 coroutineScope : CoroutineScope ? = null
191180): DataSaverMutableState <T > {
192181 val saverInterface = getLocalDataSaverInterface()
193182 var state: DataSaverMutableState <T >? = null
183+ val restorer by remember(initialValue, typeConverter) {
184+ lazy {
185+ typeConverter?.asRestorer(initialValue)
186+ ? : DataSaverConverter .findRestorer<T >(initialValue)
187+ }
188+ }
194189
195190 LaunchedEffect (key1 = senseExternalDataChange) {
196191 if (! senseExternalDataChange || state == null ) return @LaunchedEffect
@@ -204,7 +199,7 @@ inline fun <reified T> rememberDataSaverState(
204199 if (k == key && v != state?.value) {
205200 val d = if (v != null ) {
206201 if (v is String ) {
207- val restore = DataSaverConverter .findRestorer< T >(initialValue) ? : unsupportedType(initialValue, " restore" )
202+ val restore = restorer ? : unsupportedType(initialValue, " restore" )
208203 restore(v) as T
209204 } else {
210205 (v as ? T ) ? : unsupportedType(v, " restore" )
@@ -230,8 +225,8 @@ inline fun <reified T> rememberDataSaverState(
230225 }
231226 }
232227
233- return remember(saverInterface, key, async) {
234- mutableDataSaverStateOf(saverInterface, key, initialValue, savePolicy, async, coroutineScope).also {
228+ return remember(saverInterface, key, initialValue, typeConverter, savePolicy, async, coroutineScope ) {
229+ mutableDataSaverStateOf(saverInterface, key, initialValue, typeConverter, savePolicy, async, coroutineScope).also {
235230 state = it
236231 }
237232 }
@@ -245,6 +240,7 @@ inline fun <reified T> rememberDataSaverState(
245240 *
246241 * @param key String
247242 * @param initialValue T default value if it is initialized the first time
243+ * @param typeConverter ITypeConverter? specific type converter for this state, the priority is higher than the global one
248244 * @param savePolicy how and when to save data, see [SavePolicy]
249245 * @param async whether to save data asynchronously
250246 * @param coroutineScope CoroutineScope? the scope to launch coroutine, if null, it will create one with [Dispatchers.IO]
@@ -256,6 +252,7 @@ inline fun <reified T> mutableDataSaverStateOf(
256252 dataSaverInterface : DataSaverInterface ,
257253 key : String ,
258254 initialValue : T ,
255+ typeConverter : ITypeConverter ? = null,
259256 savePolicy : SavePolicy = SavePolicy .IMMEDIATELY ,
260257 async : Boolean = true,
261258 coroutineScope : CoroutineScope ? = null
@@ -264,13 +261,19 @@ inline fun <reified T> mutableDataSaverStateOf(
264261 if (! dataSaverInterface.contains(key)) initialValue
265262 else dataSaverInterface.readData(key, initialValue)
266263 } catch (e: Exception ) {
267- val restore = DataSaverConverter .findRestorer<T >(initialValue)
264+ val restore = typeConverter?.asRestorer(initialValue) ? : DataSaverConverter .findRestorer<T >(initialValue)
268265 restore ? : throw e
269266 runCatching {
270267 restore(dataSaverInterface.readData(key, " " )) as T
271268 }.onFailure {
272269 DataSaverLogger .e(" error while restoring data(key=$key ), set to default. StackTrace:\n ${it.stackTraceToString()} " )
273270 }.getOrDefault(initialValue)
274271 }
275- return DataSaverMutableState (dataSaverInterface, key, data, savePolicy, async, coroutineScope)
276- }
272+ return DataSaverMutableState (dataSaverInterface, key, data, typeConverter, savePolicy, async, coroutineScope)
273+ }
274+
275+ @PublishedApi
276+ internal inline fun ITypeConverter.asRestorer (value : Any? ): ((String ) -> Any? )? = takeIf { it.accept(value) } ?.run { ::restore }
277+
278+ @PublishedApi
279+ internal inline fun ITypeConverter.asSaver (value : Any? ): ((Any? ) -> String )? = takeIf { it.accept(value) } ?.run { ::save }
0 commit comments