【问题标题】:How to display data from view model correctly?如何正确显示视图模型中的数据?
【发布时间】:2021-10-05 05:19:00
【问题描述】:

在我的 viewModel 中,我得到了 result.data:

帐户:[Account(accountId=461715f3-038c-4c3d-ac3c-1fac44f37f14, currency=GBP, description=Personal,nickname=Sydney Beard)]

ViewModel的代码如下:

@HiltViewModel
class AccountListViewModel @Inject constructor(
    private val getAccountsUseCase: GetAccountsUseCase,
    savedStateHandle: SavedStateHandle
): ViewModel() {

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

    init {
        savedStateHandle.get<String>(Constants.ACCESS_TOKEN)?.let { accessToken ->
            getAccounts(accessToken = accessToken)
        }
    }

    private fun getAccounts(accessToken: String) {
        getAccountsUseCase(accessToken = accessToken).onEach { result ->
            when (result) {
                is Resource.Success -> {
                    _state.value = AccountListState(accounts = result.data ?: emptyList())
                }
                is Resource.Error -> {
                    _state.value = AccountListState(error = result.message ?: "Something went wrong")
                }
                is Resource.Loading -> {
                    _state.value = AccountListState(isLoading = true)
                }
            }
        }.launchIn(viewModelScope)
    }
}

在我的日志屏幕中,我看到我获得了帐户:

帐户:帐户(accountId=461715f3-038c-4c3d-ac3c-1fac44f37f14,货币=GBP,描述=个人,昵称=悉尼胡须)

这是我的屏幕代码:

@ExperimentalMaterialApi
@Composable
fun OverviewScreen(
    navController: NavController,
    viewModel: AccountListViewModel = hiltViewModel()
) {

    val state = viewModel.state.value
    Box(modifier = Modifier.fillMaxSize()) {
        LazyColumn(modifier = Modifier.fillMaxSize()) {
            items(state.accounts) { account ->
                Log.d("some", "account: $account")
                AccountListItem(
                    account = account,
                    onItemClick = {
                        navController.navigate(Screen.AccountDetail.route + "/${account.accountId}")
                    }
                )
            }
        }
        if (state.error.isNotBlank()) {
            Text(
                text = state.error,
                color = MaterialTheme.colors.error,
                textAlign = TextAlign.Center,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 20.dp)
                    .align(Alignment.Center)
            )
        }
        if (state.isLoading) {
            CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
        }
    }
}

但很遗憾,我在屏幕上看不到任何内容,尽管我是这样显示我的帐户的。

问:如何显示我的帐户,因为现在我多次调用getAccounts 方法,这就是为什么每次都重绘屏幕的原因

更新

我检查了我的AccountListViewModel 实例并在方法getAccounts() 中放置下一个日志:

Log.d("some", "getAccounts: ${result.data} vm: ${this.toString()}")

看到这一点,我看到每次重新创建视图模型时:

【问题讨论】:

    标签: android kotlin mvvm android-jetpack-compose


    【解决方案1】:

    在 Compose 中,您必须将流程收集为一个状态。您只在代码中读取一次流。

    您还在 ViewModel 中使用状态,这很糟糕。在那里使用流。

    ViewModel 中的修复:

    // wrong
    private val _state = mutableStateOf<AccountListState>(AccountListState())
        val state: State<AccountListState> = _state
    
    // correct
    private val _state = MutableStateFlow<AccountListState>(AccountListState())
        val state: StateFlow<AccountListState> = _state
    

    并在 compose 中修复:

    // wrong
    val state = viewModel.state.value
    
    // correct
    val state by viewModel.state.collectAsState()
    

    在此处阅读更多信息:https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#(kotlinx.coroutines.flow.StateFlow).collectAsState(kotlin.coroutines.CoroutineContext)

    【讨论】:

    • 我不能在我的屏幕上这样写:val state by viewModel.state.collectAsState() 因为collectAsState 未解析的引用。
    • 然后导入。这些在基本组成库中。 import androidx.compose.runtime.collectAsState 可能还有import androidx.compose.runtime.getValue
    • 添加了导入,但未使用。还收到下一条消息:public fun &lt;T&gt; StateFlow&lt;TypeVariable(T)&gt;.collectAsState(context: CoroutineContext = ...): State&lt;TypeVariable(T)&gt; defined in androidx.compose.runtime
    • 这不是错误,只是一条消息
    • 是的,你是对的,重新创建视图模型的原因是导航不正确,问题没有涉及。对不起。无论如何,您的回答提示了正确的想法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2017-09-20
    相关资源
    最近更新 更多