1. 程式人生 > 其它 >MVIKotlin學習筆記(4)

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獲取更多示例。