首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Kotlin Jetpack Compose在可组合函数中显示资产文本文件

使用Kotlin Jetpack Compose在可组合函数中显示资产文本文件
EN

Stack Overflow用户
提问于 2022-01-09 19:47:52
回答 2查看 1.3K关注 0票数 3

我正在尝试从我的资产文件夹中读取一个使用Kotlin的文本文件,并将它显示给一个复合文本小部件。安卓工作室北极福克斯2020.3

下面的代码成功运行,并将文本文件显示到输出控制台,但是我不知道如何获取文本文件并将其传递给一个Compose小部件。

您会注意到,在ReadDataFile()中有两个text()调用。第一个text()位于try{}之外,工作正常,但 try{}中的text()导致一个错误:“不支持可组合函数调用”

我怎么才能把这事做好?

谢谢!

代码语言:javascript
运行
复制
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")
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-12 13:48:59

按状态刷新组成jetpack,请尝试

代码语言:javascript
运行
复制
@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"
        }

    }
}
票数 1
EN

Stack Overflow用户

发布于 2022-01-10 00:56:58

注意事项

文件读取(I/O)操作可能很长,因此不建议使用UI范围读取文件。但这并不是造成问题的原因,我只是警告你,如果它读取非常大的文件,它会使你的应用程序崩溃,因为它在UI线程中做了很长的处理。如果您不熟悉这类问题,我建议您检查此链接

解决问题的下列最佳做法

幸运的是,Jetpack compose在反应规划中工作得很好,因此我们可以利用它编写不面临上述问题的反应性代码。我做了一个和你的非常相似的例子,我希望你能理解:

UiState文件

如前所述,读取文件可能是一个很长的过程,因此让我们想象一下3种可能的状态:“加载”、“消息成功”和“错误”。在“成功消息”的情况下,我们将有一个可能为空的字符串,当消息实际从txt文件中读取时,该字符串不再为空:

代码语言:javascript
运行
复制
package com.example.kotlinreadfile

data class UiState(
    val isLoading: Boolean,
    val isOnError: Boolean,
    val fileMessage: String?
)

MainActivity.kt文件

这里将是我们的UI实现,在您的例子中,文本消息安排在应用程序中。只要我们想在屏幕上阅读这些消息,我们就会向我们的ViewModel发出请求

代码语言:javascript
运行
复制
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)在适当的范围内执行此操作。

代码语言:javascript
运行
复制
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
                    )
                }
            }
        }
    }
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70644915

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档