我正在尝试从我的资产文件夹中读取一个使用Kotlin的文本文件,并将它显示给一个复合文本小部件。安卓工作室北极福克斯2020.3
下面的代码成功运行,并将文本文件显示到输出控制台,但是我不知道如何获取文本文件并将其传递给一个Compose小部件。
您会注意到,在ReadDataFile()中有两个text()调用。第一个text()位于try{}之外,工作正常,但 try{}中的text()导致一个错误:“不支持可组合函数调用”
我怎么才能把这事做好?
谢谢!
package com.learning.kotlinreadfile
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.learning.kotlinreadfile.ui.theme.KotlinReadFileTheme
import java.io.InputStream
import java.io.IOException
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
KotlinReadFileTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
ReadDataFile()
}
}
}
}
}
@Composable
fun ReadDataFile() {
println("Read Data File")
Text("Read Data File")
val context = LocalContext.current
try {
val inputStream: InputStream = context.assets.open("data.txt")
val size: Int = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
var string = String(buffer)
println(string)
//Text(string) // ERROR: Try catch is not supported around composable function invocations
} catch (e: IOException) {
e.printStackTrace()
println("Error")
}
}
发布于 2022-01-12 13:48:59
按状态刷新组成jetpack,请尝试
@Preview
@Composable
fun ReadDataFile() {
var dataText by remember {
mutableStateOf("asd")
}
println("Read Data File")
Column {
Text("Read Data File")
Text(dataText)
}
val context = LocalContext.current
LaunchedEffect(true) {
kotlin.runCatching {
val inputStream: InputStream = context.assets.open("data.txt")
val size: Int = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
String(buffer)
}.onSuccess {
it.logE()
dataText = it
}.onFailure {
dataText = "error"
}
}
}
发布于 2022-01-10 00:56:58
注意事项
文件读取(I/O)操作可能很长,因此不建议使用UI范围读取文件。但这并不是造成问题的原因,我只是警告你,如果它读取非常大的文件,它会使你的应用程序崩溃,因为它在UI线程中做了很长的处理。如果您不熟悉这类问题,我建议您检查此链接。
解决问题的下列最佳做法
幸运的是,Jetpack compose在反应规划中工作得很好,因此我们可以利用它编写不面临上述问题的反应性代码。我做了一个和你的非常相似的例子,我希望你能理解:
UiState文件
如前所述,读取文件可能是一个很长的过程,因此让我们想象一下3种可能的状态:“加载”、“消息成功”和“错误”。在“成功消息”的情况下,我们将有一个可能为空的字符串,当消息实际从txt
文件中读取时,该字符串不再为空:
package com.example.kotlinreadfile
data class UiState(
val isLoading: Boolean,
val isOnError: Boolean,
val fileMessage: String?
)
MainActivity.kt文件
这里将是我们的UI实现,在您的例子中,文本消息安排在应用程序中。只要我们想在屏幕上阅读这些消息,我们就会向我们的ViewModel
发出请求
package com.example.kotlinreadfile
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.*
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.example.kotlinreadfile.ui.theme.KotlinReadFileTheme
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
KotlinReadFileTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
val context = LocalContext.current
viewModel.loadData(context)
ScreenContent(viewModel.uiState.value)
}
}
}
}
@Composable
fun ScreenContent(uiState: UiState) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(text = "Read Data File")
Spacer(modifier = Modifier.height(8.dp))
when {
uiState.isLoading -> CircularProgressIndicator()
uiState.isOnError -> Text(text = "Error when try load data from txt file")
else -> Text(text = "${uiState.fileMessage}")
}
}
}
}
MainViewModel.kt文件
如果您不熟悉ViewModel
类,我建议使用这个正式文件链接。在这里,我们将重点关注“我们的业务规则”,我们将做些什么来获取数据。由于我们正在处理输入/输出(I/O)操作,因此我们将使用viewModelScope.launch(Dispatchers.IO)
在适当的范围内执行此操作。
package com.example.kotlinreadfile
import android.content.Context
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.IOException
import java.io.InputStream
class MainViewModel : ViewModel() {
private val _uiState = mutableStateOf(
UiState(
isLoading = true,
isOnError = false,
fileMessage = null
)
)
val uiState: State<UiState> = _uiState
fun loadData(context: Context) {
viewModelScope.launch(Dispatchers.IO) {
try {
val inputStream: InputStream = context.assets.open("data.txt")
val size: Int = inputStream.available()
val buffer = ByteArray(size)
inputStream.read(buffer)
val string = String(buffer)
launch(Dispatchers.Main) {
_uiState.value = uiState.value.copy(
isLoading = false,
isOnError = false,
fileMessage = string
)
}
} catch (e: IOException) {
e.printStackTrace()
launch(Dispatchers.Main) {
_uiState.value = uiState.value.copy(
isLoading = false,
isOnError = true,
fileMessage = null
)
}
}
}
}
}
https://stackoverflow.com/questions/70644915
复制相似问题