(我是Android开发的新手,所以这可能是一个基本问题.我已经尽我所能地搜索了.)

我依赖于一个异步更新数据并在有新数据时提供回调的服务.我试图弄清楚如何使用它来更新我的UI时,数据的变化.

我已经看过了基本的Jetpack编写教程,我可以构建一个带有更新计数按钮的用户界面.基于这些知识,我想到的最好的 idea 是在ComponentActivity的init方法中创建一个MutableState.这是有效的,但我不知道这是否是正确的方式.

以下是我的代码(略有混淆以删除隐私细节):

class MainActivity : ComponentActivity() {

    // Get the updating value from the async service
    private val asyncService = getAsyncService()
    private val updatingValue = asyncService.getUpdatingValue()

    // Create a MutableState for the UI
    private val mutableValue = mutableStateOf(updatingValue.value)

    init {
        // Update the MutableState whenever the value changes
        updatingValue.onUpdate { newValue ->
            run {
                mutableValue.value = newValue
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ExampleComponent(mutableValue)
        }
    }
}

@Composable
fun ExampleComponent(value: MutableState<String>) {
    Text("The value is : ${value.value}")
}

这是正确的吗,还是有更好的方法来做到这一点?

最新情况:

我编写了一个这样的ViewModel类,它工作得很好:

class AsyncDataViewModel : ViewModel() {

    private val asyncService = getAsyncService()

    private val updatingValue = asyncService.getUpdatingValue()
    val value = mutableStateOf(updatingValue.value)

    init {
        updatingValue.onUpdate { updatedValue ->
            run {
                value.value = updatedValue.value
            }
        }
    }

}

推荐答案

对于Jetpack Compose,您应该使用ViewModel来管理显示的数据,如this lab中所述.一个视图模型

  • 即使发生配置更改(例如轮换),也保留数据
  • 提供对CoroutineScope的轻松访问,以异步执行挂起功能
  • 允许向Composable公开状态.

我在下面提供了一个示例体系 struct :

class MyViewModel(
    private val asyncService: AsyncService  // using Koin dependency injection
) : ViewModel() {

    private val _mutableValue = mutableStateOf("")  // for write operations
    val mutableValue: String = _mutableValue // for read operations

    init {
        this.loadValue()
    }

    fun loadValue() {
         viewModelScope.launch(Dispatchers.IO) {
             // You have a CoroutineScope here. You can execute async suspension functions here.
             // call suspension function in AsnycService class
             _mutableValue = asyncService.getUpdatingValue()  
         }
    }
}

然后,您可以按如下方式在Composable中获取您的ViewModel:

@Composable
fun MyScreen(
   amyViewModel: MyViewModel = viewModel()
) {
   Text("The value is : ${myViewModel.mutableValue}")
}

您的服务级别应该使用suspension函数.您的ViewModel将在不阻塞UI线程的情况下将此函数作为协程调用,并将自动更新值和刷新值:

class AsyncService {
    suspend fun getUpdatingValue(): String {
        delay(5000)  // some long running operation
        return "HELLO"  // value that is returned after operation  
    }
}

这样,您还可以不指定回调函数.

Android相关问答推荐

StateFlow集合AsState没有更新他的值Jetpack Compose导航

对支持哪些数据存储区方法感到困惑

Android可绘制边框删除底线

SDK 33 的问题 - 面向 S+(版本 31 及更高版本)要求在创建 PendingIntent 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE 之一

有没有办法迭代类型安全的项目访问器?

在 kotlin 协同 routine 中,如何将数据范围限定为请求路径(以 MDC 为例)?

当 Jetpack Compose 中的第一个文本很长时,将省略号添加到第一个文本

请求访问小部件中的位置权限

通知使用默认语言,屏幕显示多种语言,同时通过 AppCompatDelegate 设置应用程序语言

[Android][Room] 将密封类存储到 Room 数据库中

使用 Kotlin 在 Android 中导航时如何防止 ViewModel 被杀死?

未找到 com.android.tools.build:gradle:7.4.0 的匹配变体

如何在 Jetpack Compose 中设置卡片高度

了解 Compose 声明性逻辑

Jetpack 组合千位分隔符视觉转换,也适用于小数

GridLayout 和 GridView 有什么好用和区别

Horizo​​ntalPager 的可组合物中的 LaunchedEffect 问题

如何从 Jetpack Compose 中的 Radio 组中获取价值

如何使用jetpack compose实现布局,其中图标在列布局上是绝对位置

错误:没有这样的属性:类的组:org.gradle.api.publication.maven.internal.ant.DefaultGroovyMavenDeployer