当 ViewModel 内的状态发生更改时,可组合项不会重新组合

问题描述 投票:0回答:1

当通过将同步状态设置为 true 开始同步文件时,我试图显示一个循环进度指示器。 当同步结束时,变量变为 false。

这是我的 MainViewModel 的代码。

public val syncing  = MutableStateFlow(false)

fun syncFiles(context: Context) {
        if ((getApplication<MainApplication>()).dropboxClient?.isClientReady() != true) {
            showShortToast(context, "Dropbox is not connected")
            return;
        }

        viewModelScope.launch {
            syncing.update {true}
            val result = withContext(Dispatchers.IO) {
                var result = false;
                try {
                    getApplication<MainApplication>().initlializeDropboxFromLocalCreds()
                    updateMyData()
                    saveFiles()
                    Timber.d(bookRepo.getAllBooks().joinToString(", "))
                    result = true;
                } catch (it: Exception) {
                    Timber.tag("Error").e(it.toString())
                    result = false
                }
                syncing.update {false}
                result;
            }

            if (result) {
                showShortToast(context, "Books synced properly")
            } else {
                showShortToast(context, "Couldn't sync books")
            }
        }
}

但是可组合项内部的状态不会改变。

我已经调试了该问题,并且可组合项仅在应用程序启动时构造一次。

fun MainPage(
    innerPadding: PaddingValues,
    modifier: Modifier = Modifier,
    navigateToReader: (filePath: String) -> Unit,
    mainViewModel: MainViewModel = viewModel()
) {

    Box {
        val state by  mainViewModel.syncing.collectAsState()
        if (state) {
            CircularProgressIndicator(
//                progress = { currentProgress },
                modifier = Modifier.fillMaxWidth(),
                color = MaterialTheme.colorScheme.primary,
                trackColor = MaterialTheme.colorScheme.surfaceVariant,
            )
        } else {
            Column(
                modifier = Modifier
                    .padding(innerPadding)
                    .padding(horizontal = 15.dp, vertical = 20.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp),
            ) {
                Greeting(navigateToReader = navigateToReader)
            }
        }
    }
}

我尝试过

mutableStateOf
remember
mutableStateOf
结合使用,但没有任何效果。

请解释为什么会发生这种情况。

我已尝试调试该问题,但可组合仅组合一次。

我希望状态在同步开始时更改为 true,在同步结束时更改为 false(这正在发生)。 UI 应相应更新以显示循环进度指示器(这并未发生)。

android android-jetpack-compose state viewmodel
1个回答
0
投票

a) ViewModel 中的主要变化:

  1. 使用私有 MutableStateFlow (_syncing) 和公共 StateFlow (syncing) 以获得更好的封装。

  2. 使用 _syncing.value = true 和 _syncing.value = false 更新状态。

     class MainViewModel : ViewModel() {
    
     private val _syncing = MutableStateFlow(false)
     val syncing: StateFlow<Boolean> = _syncing
    
     fun syncFiles(context: Context) {
         if ((getApplication<MainApplication>()).dropboxClient?.isClientReady() != true) {
             showShortToast(context, "Dropbox is not connected")
             return
         }
    
         viewModelScope.launch {
             _syncing.value = true
             val result = withContext(Dispatchers.IO) {
                 var result = false
                 try {
                     getApplication<MainApplication>().initlializeDropboxFromLocalCreds()
                     updateMyData()
                     saveFiles()
                     Timber.d(bookRepo.getAllBooks().joinToString(", "))
                     result = true
                 } catch (it: Exception) {
                     Timber.tag("Error").e(it.toString())
                     result = false
                 }
                 result
             }
             _syncing.value = false
    
             if (result) {
                 showShortToast(context, "Books synced properly")
             } else {
                 showShortToast(context, "Couldn't sync books")
             }
          }
       }
    }
    

b) 可组合项的主要变化:

  1. 通过 mainViewModel.syncing.collectAsState() 使用 val state 观察状态。

  2. 确保 Box 使用modifier = modifier.fillMaxSize() 以获得正确的布局。

     fun MainPage(
     innerPadding: PaddingValues,
     modifier: Modifier = Modifier,
     navigateToReader: (filePath: String) -> Unit,
     mainViewModel: MainViewModel = viewModel()) {
    
     val state by mainViewModel.syncing.collectAsState()
    
     Box(modifier = modifier.fillMaxSize()) {
         if (state) {
             CircularProgressIndicator(
                 modifier = Modifier.fillMaxWidth(),
                 color = MaterialTheme.colorScheme.primary,
                 trackColor = MaterialTheme.colorScheme.surfaceVariant,
             )
         } else {
             Column(
                 modifier = Modifier
                     .padding(innerPadding)
                     .padding(horizontal = 15.dp, vertical = 20.dp),
                 verticalArrangement = Arrangement.spacedBy(16.dp),
             ) {
                 Greeting(navigateToReader = navigateToReader)
             }
          }
       }
    }
    

通过进行这些更改,您的可组合项应该正确观察同步状态并在状态更改时重新组合,在同步时显示 CircularProgressIndicator,在不同步时显示 Column。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.