Squ*_*eOJ 4 kotlin android-jetpack-compose
我正在尝试使用 Kotlin 从我的 Assets 文件夹中读取文本文件并将其显示到 Compose 文本小部件。Android Studio 北极狐 2020.3
以下代码成功运行并将文本文件显示到输出控制台,但是我无法弄清楚如何获取文本文件并将其传递到 Compose 文本小部件。
您会注意到我在 ReadDataFile() 内有 2 个 text() 调用。第一个 text() 位于 try{} 之外,并且工作正常,但是try{} 内的 text() 会导致错误:“可组合函数调用不支持 Try catch”
我怎样才能做到这一点?
谢谢!
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")
}
}
Run Code Online (Sandbox Code Playgroud)
Pie*_*ira 12
文件读取 (I/O) 操作可能会很长,因此不建议使用 UI 范围来读取文件。但这并不是导致问题的原因,我只是警告您,如果它读取非常大的文件,它可能会使您的应用程序崩溃,因为它在 UI 线程中进行了很长的处理。如果您不熟悉此类问题,我建议您检查此链接。
幸运的是,Jetpack compose 与响应式编程配合得很好,因此我们可以利用它来编写不会面临上述问题的响应式代码。我举了一个和你很相似的例子,希望你能理解:
如前所述,读取文件可能是一个漫长的过程,因此让我们想象 3 种可能的状态:“正在加载”、“消息成功”和“错误”。在“成功消息”的情况下,我们将有一个可能为空的字符串,当实际从文件中读取消息时,该字符串将不再为空txt
:
package com.example.kotlinreadfile
data class UiState(
val isLoading: Boolean,
val isOnError: Boolean,
val fileMessage: String?
)
Run Code Online (Sandbox Code Playgroud)
这只是我们的 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}")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不熟悉该类,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
)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3967 次 |
最近记录: |