(我是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相关问答推荐

如何使禁用状态下的material 3按钮与启用状态下的 colored颜色 相同?

Android compose ,在图像中zoom 而不裁剪?

Jetpack创作动画断断续续变化的观点

如何更新Kotlin中的显示?

我正在创建一个简单的连接四个游戏,我需要一个弹出式窗口当你赢了

为什么可以';我不能直接在RecyclerView.ViewHolder中访问视图ID吗?

Android 导航 - 定义参数

Android kotlin 中闪屏 API 执行完成后如何根据身份验证将用户导航到特定屏幕

Material 3的MaterialSwitch默认大小太大了?如何使它变小?

Android - 如何使 TextInputEditText 的高度恰好为 2 行?

在 Android 房间迁移中获取上下文

在 jetpack compose 中交替使用 View.INVISIBLE

如何添加到先前预填充的 Room 数据库?

当包含可绘制对象的整数变量传递给 painterResource 函数时,为什么图像不在 Android Studio 中呈现?

在 Jetpack Compose 中使用 .observeAsState() 时,如何在更改 MutableLiveData 的值后开始执行一段代码?

为什么官方文档用大写字母表示val变量?

复用 RecyclerView 适配器,避免不必要的 API 调用

如何使用文件提供程序将视频从一个应用程序共享到另一个应用程序?

构成material 3 中的分隔符

如何使用 Jetpack Compose 在应用程序中实现本地化