繁体   English   中英

Jetpack 撰写数据存储不断重组屏幕

[英]Jetpack compose data store keeps recomposing screen

我正在使用 jetpack compose 从共享偏好迁移到数据存储。 一切正常(数据已保存并可成功撤回)。 但是,每当检索到数据时,可组合项就会不断地重新组合。 我正在使用 MVVM 架构,下面是我实现数据存储的方式。

下面在我的 AppModule.kt 中声明

SingletonComponent 中的应用模块

@Provides
@Singleton
fun provideUserPreferenceRepository(@ApplicationContext context: Context):
        UserPreferencesRepository = UserPreferencesRepositoryImpl(context)

然后这是我的 ViewModel:

@HiltViewModel
class StoredUserViewModel @Inject constructor(
private val _getUserDataUseCase: GetUserDataUseCase
): ViewModel() {

private val _state = mutableStateOf(UserState())
val state: State<UserState> = _state

fun getUser(){
    _getUserDataUseCase().onEach { result ->
        val name = result.name
        val token = result.api_token
        val balance = result.balance
        val agentCode = result.agent_code
        _state.value = UserState(user = UserPreferences(name, agentCode, token, balance))
    }.launchIn(viewModelScope)
 }}

最后,这是我的存储库实现:

class UserPreferencesRepositoryImpl @Inject constructor(
private val context: Context
): UserPreferencesRepository {

private val Context.dataStore by preferencesDataStore(name = "user_preferences")
}
private object Keys {
    val fullName = stringPreferencesKey("full_name")
    val api_token = stringPreferencesKey("api_token")
    val balance = intPreferencesKey("balance")
    val agentCode = intPreferencesKey("agent_code")
}

private inline val Preferences.fullName get() = this[Keys.fullName] ?: ""
private inline val Preferences.apiToken get() = this[Keys.api_token] ?: ""
private inline val Preferences.balance get() = this[Keys.balance] ?: 0
private inline val Preferences.agentCode get() = this[Keys.agentCode] ?: 0

override val userPreferences: Flow<UserPreferences> = context.dataStore.data.catch{
//        throws an IOException when an error is encountered when reading data
    if (it is IOException) {
        emit(emptyPreferences())
    } else {
        throw it
    }
}.map { preferences ->
    UserPreferences(name = preferences.fullName, agent_code = preferences.agentCode, api_token = preferences.apiToken,
        balance = preferences.balance)
}.distinctUntilChanged()

我不知道是什么导致可组合重组。 以下是可组合的:

@Composable
fun LoginScreen(
navController: NavController,
userViewModel: StoredUserViewModel = hiltViewModel()
) {

Log.v("LOGIN_SCREEN", "CALLED!")
userViewModel.getUser()
}

如果有人能告诉我哪里做错了,请赐教。 我试图在 AppModule 中更改 UserPreferencesRepository 的实现,但没有运气。

下面是 UseState.kt,它只是一个数据 class

data class UserState(
val user: UserPreferences? = null
)

下面是 UserPreferences.kt

data class UserPreferences(val name: String, val agent_code: Int, val api_token: String, val balance: Int)

这是预期的行为:您在每次重组时都调用getUser

@Composable function 是一个视图构建器,应该没有副作用。

相反,您可以使用特殊的副作用 function,例如LaunchedEffect ,它只会启动一次作业,直到它从视图树中删除或更改key参数:

LaunchedEffect(Unit) {
    userViewModel.getUser()
}

但这也将在配置更改的情况下被重新调用,例如屏幕旋转。 为了防止这种情况,您有两种选择:

  1. 在视图 model init中调用getUser :在这种情况下,它保证只调用一次。
  2. 在视图 model 内创建一些标志以防止冗余请求。

文档中有关撰写副作用的更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM