MVIKotlin学习笔记(4):状态保存与日志记录

状态保存

有时为了以后恢复状态,保存一个状态是有必要的。一个十分常见的使用情况是由于配置更改或进程结束而重新创建的安卓Activity。如果是一个纯安卓项目(不是多平台),可以直接使用AndroidX的SavedStateRegistry。对于多平台项目,可以使用Essenty库中的StateKeeper

保留对象

另一种使用情况是在作用域重新创建后保留对象实例,这在安卓的配置发生变化时很常见。如果是一个纯安卓项目(不是多平台),可以直接使用AndroidX的ViewModelStoreViewModelProvider。对于多平台项目,可以使用Essenty库中的InstanceKeeper

示例

保存Store的State

internal interface CalculatorStore : Store<Intent, State, Nothing> {
    @Parcelize
    data class State(
        val isLoading: Boolean = false,
        // 其他属性
    ) : Parcelable

    // 其他代码
}

internal class CalculatorStoreFactory(private val storeFactory: StoreFactory) {

    fun create(stateKeeper: StateKeeper): CalculatorStore =
        object : CalculatorStore, Store<Intent, State, Nothing> by storeFactory.create(
            name = "CounterStore",
            initialState = stateKeeper.consume(key = "CalculatorStoreState") ?: State(),
            executorFactory = ::ExecutorImpl,
            reducer = ReducerImpl
        ) {
        }.also {
            stateKeeper.register(key = "CalculatorStoreState") {
                it.state.copy(isLoading = false) // 可以在这里重置任何瞬时状态
            }
        }

    // 其他代码
}

保留整个Store

import com.arkivanov.essenty.instancekeeper.InstanceKeeper
import com.arkivanov.mvikotlin.core.instancekeeper.getStore

class CalculatorController(instanceKeeper: InstanceKeeper) {

    private val store: CalculatorStore =
        instanceKeeper.getStore(::calculatorStore)

    /*
     * 创建一个CalculatorStore的实例。
     * ⚠️ 注意不要缺少任何依赖项。
     */
    private fun calculatorStore(): CalculatorStore = // 创建一个Store
}

保留任意对象

import com.arkivanov.essenty.instancekeeper.InstanceKeeper
import com.arkivanov.essenty.instancekeeper.getOrCreate

class CalculatorController(instanceKeeper: InstanceKeeper) {

    private val something: Something =
        instanceKeeper.getOrCreate(::Something)

    /*
     * 将被保留的类实例。
     * ⚠️ 注意不要缺少任何依赖项。
     */
    private class Something : InstanceKeeper.Instance {
        override fun onDestroy() {
            // 清理这里的所有资源
        }
    }
}

在安卓中创建StateKeeper

import com.arkivanov.essenty.statekeeper.stateKeeper

class MainActivity : AppCompatActivity() { // 与AndroidX Fragment相同

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val stateKeeper = stateKeeper()
        // 将StateKeeper传给依赖项。
    }
}

在安卓中创建InstanceKeeper

import com.arkivanov.essenty.instancekeeper.instanceKeeper

class MainActivity : AppCompatActivity() { // 与AndroidX Fragment相同

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val instanceKeeper = instanceKeeper()
        // 将InstanceKeeper传给依赖项。
    }
}

日志记录

对于任何app,日志记录总是必要的。MVIKotlin使用mvikotlin-logging模块中的 LoggingStoreFactory包装器来提供日志记录功能。可以用自定义的LoggerLogFormatter替换默认的LoggerLogFormatter

日志记录是一种调试工具,它可能会影响性能。理想情况下它不应该在生产环境中使用。

使用LoggingStoreFactory

假设我们有以下的Store工厂:

internal class CalculatorStoreFactory(private val storeFactory: StoreFactory) {

    fun create(): CalculatorStore =
        object : CalculatorStore, Store<Intent, State, Nothing> by storeFactory.create(
            name = "CounterStore",
            // ...
        ) {
        }

    // ...
}

它接受一个StoreFactory,并用它创建一个CalculatorStore的实例。现在在这里可以传递任何StoreFactory。因此,如果你想要增加日志记录,只需要传递一个LoggingStoreFactory的实例:

val storeFactory = LoggingStoreFactory(DefaultStoreFactory)

CalculatorStoreFactory(storeFactory).create()

通常需要在主程序的某处定义一个全局的StoreFactory,并将它传递给所有依赖项。

可以参阅samples获取更多示例。

热门相关:超武穿梭   豪门闪婚:帝少的神秘冷妻   明月照大江   刺客之王   第一神算:纨绔大小姐