强制重组(Android compose)



首先,代码:

import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.unit.dp
import com.example.saveandloadusername.ui.theme.SaveAndLoadUserNameTheme
import java.io.File
import java.io.IOException
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SaveAndLoadUserNameTheme {
Surface(color = MaterialTheme.colors.background) {
MainScreen(baseContext)
}
}
}
}
}
@Composable
fun MainScreen(context: Context) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
)
{
var name by remember { mutableStateOf("")}
if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
Text(text="Hello, give me your name :)")
} else {
Text(text="welcome back ${readNameFromInternalStorage(context)}")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
OutlinedTextField(
value=name,
onValueChange={ name = it },
label={Text(text="Name")},
singleLine = true,
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Words)
)
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(
onClick = {
name = name.replace(" ", "".replace("n", ""))
if(name == "") {
Toast.makeText(context, "name invalid", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "name (${name}) saved :D", Toast.LENGTH_SHORT).show()
saveNameToInternalStorage(name, context)
}
},
)
{
Text(text="save")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(
onClick = {
if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
Toast.makeText(context, "you need to give me a name first ;)", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(
context,
"the name is: '${readNameFromInternalStorage(context)}'",
Toast.LENGTH_SHORT
).show()
}
},
)
{
Text(text="check")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(onClick = { cleanNameData(context)}) {
Text("Remove name")
}
}
}
private fun saveNameToInternalStorage(name: String, context: Context): Boolean {
return try {
context.applicationContext.openFileOutput("name.txt", MODE_PRIVATE).use { stream ->
stream.flush()
stream.write(name.toByteArray())
Log.i("SAVE_STATE","name ($name) written as ${name.toByteArray()}")
}
return true
} catch(e: IOException) {
e.printStackTrace()
false
}
}
private fun readNameFromInternalStorage(context: Context): String {
val file = File(context.filesDir, "name.txt")
return if (file.exists()) {
val contentOfFile = file.readBytes().decodeToString()
Log.i("CONTENTTT", contentOfFile)
contentOfFile
} else {
""
}
}
private fun checkIfNameIsEmpty(name: String): Boolean {
return name.isEmpty()
}
private fun cleanNameData(context: Context) {
context.applicationContext.openFileOutput("name.txt", MODE_PRIVATE).use { stream ->
stream.flush()
Log.i("cleanNameData", "Name Removed from memory")
Toast.makeText(context, "Name removed", Toast.LENGTH_SHORT).show()
}
}

我创建了一个小应用程序来了解android撰写,我偶然发现了一个问题,我无法解决,文本(即在TextField之上)不更新按钮"删除名称"或";save"按下,文本只有更新时,某些东西在文本框的变化,是否有一种方法来强制手动重组该文本?感谢任何帮助:)

首先,如果您所需要做的就是在那里显示那个名称,那么为什么要麻烦地将它存储到存储器中,然后再读取呢?建议:可以直接使用name参数作为Text的值,修改后直接将新名称存储到存储中,如果交易成功,再更新变量。它将触发必要的重组。

接下来,文本没有更新的原因是因为您从存储中获取名称的方法返回的是原始类型,而不是LiveData。因此,如果您正在自己实现该方法,请先尝试阅读有关LiveData的内容,而不是手动触发重新组合。这应该不难实现。

然而(不推荐),如果你想要的只是一个手动重新触发合成的方法,那么这里就是。

您可能知道,Compose使用MutableState对象来观察数据,您似乎对此非常熟悉,因为您已经在使用它了。因此,您所需要做的只是添加类型为MutableState的"虚拟"变量,然后从相关按钮的onClicks修改它。此外,您必须给Compose一个消息,表示在Text中正在读取虚拟变量,因此它将触发重新组合。

@Composable
fun MainScreen(context: Context) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
)
{
var name by remember { mutableStateOf("")}
var dummy by mutableStateOf(false) // don't even need to remember, long as it compiles
if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
dummy
Text(text="Hello, give me your name :)")
} else {
dummy
Text(text="welcome back ${readNameFromInternalStorage(context)}")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
OutlinedTextField(
value=name,
onValueChange={ name = it },
label={Text(text="Name")},
singleLine = true,
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Words)
)
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(
onClick = {
dummy = !dummy // modify to trigger recomposition
name = name.replace(" ", "".replace("n", ""))
if(name == "") {
Toast.makeText(context, "name invalid", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "name (${name}) saved :D", Toast.LENGTH_SHORT).show()
saveNameToInternalStorage(name, context)
}
},
)
{
Text(text="save")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(
onClick = {
dummy = !dummy // The same here
if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
Toast.makeText(context, "you need to give me a name first ;)", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(
context,
"the name is: '${readNameFromInternalStorage(context)}'",
Toast.LENGTH_SHORT
).show()
}
},
)
{
Text(text="check")
}
Spacer(modifier = Modifier
.height(10.dp)
.fillMaxWidth())
Button(onClick = {
dummy = !dummy //That's all
cleanNameData(context)
}) {
Text("Remove name")
}
}
}

这个应该可以。

嘿,你也不需要粘贴整个代码库。只要提供必要的部分,如果需要,我们会要求更多的。谢谢你,

在下面的代码块中,您没有在任何地方使用name变量

if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
Text(text="Hello, give me your name :)")
} else {
Text(text="welcome back ${readNameFromInternalStorage(context)}")
}

所以,改变name的值不会对重组产生任何影响。如果你真的想,你需要(有点)有remember{readNameFromInternalStorage(context)}

最新更新