Android 中基于 Jetpack Compose 的屏幕的 entry/load 从网络或数据库获取数据
Get data from network or database on entry/load of a Jetpack Compose based screen in Android
我是 Jetpack Compose 和 Kotlin 的新手,但我正在尝试使用最近 stable Jetpack Compose v1.0.0.0
开发移动应用程序
我正在使用 NavController
进行导航,我的屏幕是使用可组合函数制作的。
因为我的屏幕本身就是一个可组合函数,所以我无法理解如何在可组合函数条目上加载一些 API/DB 数据。
我试图阅读有关 LaunchedEffect
的内容,但不知道这是否是正确的方法,而且实施起来似乎也很复杂。
示例代码如下:
DemoScreen.kt
:将此视为我在 NavHost
.
中的 startDestination
的屏幕
@可组合
有趣的 DemoScreen(navController:NavController){
var json = "Placeholder content, to be updated on screen load and refreshed every x seconds..."
//1. Make network or DB call as soon as entering this composable and store in the "json" variable
//makeDataLoadCallOnEntry() //something like this, and show processing indicator...
//2. And then keep refreshing/updating the content of the "json" variable by calling this
//function in a timer
Box(modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
){
//region #Region: Main content area
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 0.dp)
//.padding(top = 120.dp)
) {
TextField(
value = json,
onValueChange = { json = it },
singleLine = false,
modifier = Modifier
.fillMaxWidth()
.padding(5.dp)
.height(500.dp),
maxLines = 10,
)
val coroutineScope = rememberCoroutineScope()
Button(
onClick = {
coroutineScope.launch {
withContext(Dispatchers.IO) {
try {
//do something in button click
} catch (e: Exception) {
// handle exception
Log.d("button", e.message.toString())
} finally {
//do something
Log.d("button", "in finally")
}
}
}
},
modifier = Modifier
.fillMaxWidth()
.padding(5.dp)
.height(100.dp)
) {
Text(text = "Demo Button")
}
}
//endregion
}
}
我的 NavHost
看起来像这样(工作正常):
@可组合
有趣的 NavigationMaster() {
val navController = rememberNavController()
val defaultScreen = Screens.DemoScreen.route
NavHost(
navController = navController,
startDestination = defaultScreen){
composable(
route = Screens.DemoScreen.route
){
DemoScreen(navController = navController)
}
}
}
如何在我的 DemoScreen
可组合条目上调用一个函数,以便在呈现屏幕之前从我的 API 获取数据。
如果我能得到上面的,那么我想我应该能够实现定时器部分,使用循环 and/or 定时器自动刷新来自 API 的数据。
这是该屏幕当前外观的演示屏幕截图(演示按钮不执行任何操作,请忽略它):
您可以使用 view model 来完成,像这样:
@Composable
fun DemoScreen() {
val viewModel = viewModel<DemoScreenViewModel>()
when (val state = viewModel.state.collectAsState().value) {
DemoScreenViewModel.State.Loading -> {
Text("Loading")
}
is DemoScreenViewModel.State.Data -> {
DemoScreenContent(state.data)
}
}
}
class DemoScreenViewModel : ViewModel() {
sealed class State {
object Loading: State()
data class Data(val data: String): State()
}
private var _state = MutableStateFlow<State>(State.Loading)
val state = _state.asStateFlow()
init {
viewModelScope.launch {
while (isActive) {
val data = makeDataLoadCallOnEntry()
_state.value = State.Data(data)
// wait one minute and repeat your request
delay(60 * 1000L)
}
}
}
suspend fun makeDataLoadCallOnEntry(): String {
delay(1000)
return "Hello world"
}
}
最简单的方法是在您的 main activity 中的 onCreate
块的开头调用 super.onCreate(...)
后立即加载它。关于刷新的事情,你可以只使用一个循环。
我是 Jetpack Compose 和 Kotlin 的新手,但我正在尝试使用最近 stable Jetpack Compose v1.0.0.0
开发移动应用程序我正在使用 NavController
进行导航,我的屏幕是使用可组合函数制作的。
因为我的屏幕本身就是一个可组合函数,所以我无法理解如何在可组合函数条目上加载一些 API/DB 数据。
我试图阅读有关 LaunchedEffect
的内容,但不知道这是否是正确的方法,而且实施起来似乎也很复杂。
示例代码如下:
中的DemoScreen.kt
:将此视为我在NavHost
.startDestination
的屏幕@可组合 有趣的 DemoScreen(navController:NavController){
var json = "Placeholder content, to be updated on screen load and refreshed every x seconds..." //1. Make network or DB call as soon as entering this composable and store in the "json" variable //makeDataLoadCallOnEntry() //something like this, and show processing indicator... //2. And then keep refreshing/updating the content of the "json" variable by calling this //function in a timer Box(modifier = Modifier .fillMaxWidth() .fillMaxHeight() ){ //region #Region: Main content area Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() .padding(horizontal = 0.dp) //.padding(top = 120.dp) ) { TextField( value = json, onValueChange = { json = it }, singleLine = false, modifier = Modifier .fillMaxWidth() .padding(5.dp) .height(500.dp), maxLines = 10, ) val coroutineScope = rememberCoroutineScope() Button( onClick = { coroutineScope.launch { withContext(Dispatchers.IO) { try { //do something in button click } catch (e: Exception) { // handle exception Log.d("button", e.message.toString()) } finally { //do something Log.d("button", "in finally") } } } }, modifier = Modifier .fillMaxWidth() .padding(5.dp) .height(100.dp) ) { Text(text = "Demo Button") } } //endregion }
}
我的
NavHost
看起来像这样(工作正常):@可组合 有趣的 NavigationMaster() { val navController = rememberNavController() val defaultScreen = Screens.DemoScreen.route
NavHost( navController = navController, startDestination = defaultScreen){ composable( route = Screens.DemoScreen.route ){ DemoScreen(navController = navController) } }
}
如何在我的
DemoScreen
可组合条目上调用一个函数,以便在呈现屏幕之前从我的 API 获取数据。如果我能得到上面的,那么我想我应该能够实现定时器部分,使用循环 and/or 定时器自动刷新来自 API 的数据。
这是该屏幕当前外观的演示屏幕截图(演示按钮不执行任何操作,请忽略它):
您可以使用 view model 来完成,像这样:
@Composable
fun DemoScreen() {
val viewModel = viewModel<DemoScreenViewModel>()
when (val state = viewModel.state.collectAsState().value) {
DemoScreenViewModel.State.Loading -> {
Text("Loading")
}
is DemoScreenViewModel.State.Data -> {
DemoScreenContent(state.data)
}
}
}
class DemoScreenViewModel : ViewModel() {
sealed class State {
object Loading: State()
data class Data(val data: String): State()
}
private var _state = MutableStateFlow<State>(State.Loading)
val state = _state.asStateFlow()
init {
viewModelScope.launch {
while (isActive) {
val data = makeDataLoadCallOnEntry()
_state.value = State.Data(data)
// wait one minute and repeat your request
delay(60 * 1000L)
}
}
}
suspend fun makeDataLoadCallOnEntry(): String {
delay(1000)
return "Hello world"
}
}
最简单的方法是在您的 main activity 中的 onCreate
块的开头调用 super.onCreate(...)
后立即加载它。关于刷新的事情,你可以只使用一个循环。