![](/img/trans.png)
[英]Wait for Preferences Datastore to retrieve data from preferences datastore in workmanager
[英]How do I wait until data from Preferences DataStore is loaded?
我正在嘗試制作 LibGDX 動態壁紙。 但我認為這與我目前遇到的問題無關。 基本上,我將牆紙的設置存儲在 Preferences DataStore 中。 現在,如果您需要從 DataStore 檢索數據,則需要檢索 Kotlin Flow
並使用它來獲取首選項。 在 LibGDX 的ApplicationListener
的onCreate()
方法中,我需要創建一個 KtxScreen object。我決定將所有首選項傳遞到我的Screen
的構造函數中。 但是,由於Flow
的數據只能在協程內獲取,因此我無法使用用戶首選項作為構造函數參數來構造我的KtxScreen
object,因為我需要等到我的Flow
發出值。 我用一段非常非常臟的while (userPreferences == null) Unit
代碼解決了這個問題,它基本上阻止了整個應用程序,直到發出首選項,這樣我才能構建我的KtxScreen
。 解決這個問題的好方法是什么?
在 libGDX 中阻塞渲染線程是可以接受的。 這是一個獨立於 Android 主線程的線程,因此它不會凍結 Android UI 或讓您面臨 ANR(應用程序未響應錯誤)的風險。 它會在阻塞時凍結任何游戲/牆紙渲染,但是當您仍在加載場景時這沒關系。
所以,在create()
或render()
中使用runBlocking
來等待第一批設置是可以接受的。 由於 KtxScreen 不使用create()
,您可以直接在屬性初始化時阻塞。 您可以在 Flow 上調用first()
以僅從中獲取一個項目,這對於 KtxScreen class 的初始設置來說很好。
如果您使用的是 libKtx 中的ktx-async
庫,您可以在渲染線程上收集您的流程,這樣如果用戶在您的牆紙運行時更新設置,它會安全地更新您的設置。
這是您如何實現這一目標的一個示例(我沒有測試它),但是有許多可接受的不同方式可以處理它。 注意:這是假設您在渲染線程而不是 Android 主線程上實例化此屏幕。 渲染線程用於在您的游戲 class 上調用create()
,這是實例化您的第一個屏幕的典型位置。
class MyScreen(
val settingsFlow: Flow<UserPreferences>
): KtxScreen {
var prefs: UserPreferences = runBlocking { settingsFlow.first() }
init {
settingsFlow
.drop(1) // the first one should be the value we already got above
// unless the user changed them impossibly fast
.onEach { prefs = it }
.launchIn(KtxAsync)
}
//...
}
如果你想在你的壁紙中顯示某種初始加載圖像,你可以像這樣在你的render
function 中使用 if/else。 但我不認為這是必要的,因為偏好可能需要不到半秒的時間來加載。
class MyScreen(
val settingsFlow: Flow<UserPreferences>
): KtxScreen {
var _prefs: UserPreferences? = null
init {
settingsFlow
.onEach { _prefs = it }
.launchIn(KtxAsync)
}
override fun render() {
val prefs = _prefs // for the sake of smart-casting
if (prefs == null) {
renderLoadingImage()
} else {
renderScene(prefs)
}
}
//...
private fun renderScene(prefs: UserPreferences) {
//...
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.