[英]Jetpack Compose saving state on orientation change
我正在使用 Android Jetpack 的 Compose,並且一直在嘗試弄清楚如何保存方向更改的狀態。
我的思路是讓一個類成為一個 ViewModel。 因為當我使用 Android 的傳統 API 時,這通常有效。
我已經使用 remember {} 和 mutableState {} 在信息發生更改時更新 UI。 請驗證我的理解是否正確...
記住 = 保存變量並允許通過 .value 訪問,這允許緩存值。 但它的主要用途是在更改時不重新分配變量。
mutableState = 在發生變化時更新變量。
許多博客文章都說要使用@Model,但是,在嘗試該方法時,導入會出錯。 所以,我添加了一個: ViewModel()
但是,我相信我記得 {} 阻止它按預期工作?
我能在正確的方向上得到一個點嗎?
@Composable
fun DefaultFlashCard() {
val flashCards = remember { mutableStateOf(FlashCards())}
Spacer(modifier = Modifier.height(30.dp))
MaterialTheme {
val typography = MaterialTheme.typography
var question = remember { mutableStateOf(flashCards.value.currentFlashCards.question) }
Column(modifier = Modifier.padding(30.dp).then(Modifier.fillMaxWidth())
.then(Modifier.wrapContentSize(Alignment.Center))
.clip(shape = RoundedCornerShape(16.dp))) {
Box(modifier = Modifier.preferredSize(350.dp)
.border(width = 4.dp,
color = Gray,
shape = RoundedCornerShape(16.dp))
.clickable(
onClick = {
question.value = flashCards.value.currentFlashCards.answer })
.gravity(align = Alignment.CenterHorizontally),
shape = RoundedCornerShape(2.dp),
backgroundColor = DarkGray,
gravity = Alignment.Center) {
Text("${question.value}",
style = typography.h4, textAlign = TextAlign.Center, color = White
)
}
}
Column(modifier = Modifier.padding(16.dp),
horizontalGravity = Alignment.CenterHorizontally) {
Text("Flash Card application",
style = typography.h6,
color = Black)
Text("The following is a demonstration of using " +
"Android Compose to create a Flash Card",
style = typography.body2,
color = Black,
textAlign = TextAlign.Center)
Spacer(modifier = Modifier.height(30.dp))
Button(onClick = {
flashCards.value.incrementQuestion();
question.value = flashCards.value.currentFlashCards.question },
shape = RoundedCornerShape(10.dp),
content = { Text("Next Card") },
backgroundColor = Cyan)
}
}
}
data class Question(val question: String, val answer: String) {
}
class FlashCards: ViewModel() {
var flashCards = mutableStateOf( listOf(
Question("How many Bananas should go in a Smoothie?", "3 Bananas"),
Question("How many Eggs does it take to make an Omellete?", "8 Eggs"),
Question("How do you say Hello in Japenese?", "Konichiwa"),
Question("What is Korea's currency?", "Won")
))
var currentQuestion = 0
val currentFlashCards
get() = flashCards.value[currentQuestion]
fun incrementQuestion() {
if (currentQuestion + 1 >= flashCards.value.size) currentQuestion = 0 else currentQuestion++
}
}
在 Compose 中有另一種處理配置更改的方法,它是rememberSaveable
。 正如文檔所說:
雖然
remember
可以幫助您在重新組合時保留狀態,但狀態不會在配置更改時保留。 為此,您必須使用rememberSaveable
。rememberSaveable
自動保存任何可以保存在 Bundle 中的值。 對於其他值,您可以傳入自定義保護程序對象。
似乎Mohammad 的解決方案更健壯,但這一個似乎更簡單。
和以前一樣,您可以使用架構組件 ViewModel 來應對配置更改。
您應該在 Activity/Fragment 中初始化您的 ViewModel,然后將其傳遞給 Composable 函數。
class UserDetailFragment : Fragment() {
private val viewModel: UserDetailViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return ComposeView(context = requireContext()).apply {
setContent {
AppTheme {
UserDetailScreen(
viewModel = viewModel
)
}
}
}
}
}
然后您的 ViewModel 應該通過 LiveData 或 Flow 之類的方式公開 ViewState
用戶詳細信息視圖模型:
class UserDetailViewModel : ViewModel() {
private val _userData = MutableLiveData<UserDetailViewState>()
val userData: LiveData<UserDetailViewState> = _userData
// or
private val _state = MutableStateFlow<UserDetailViewState>()
val state: StateFlow<UserDetailViewState>
get() = _state
}
現在您可以在可組合函數中觀察此狀態:
@Composable
fun UserDetailScreen(
viewModel:UserDetailViewModel
) {
val state by viewModel.userData.observeAsState()
// or
val viewState by viewModel.state.collectAsState()
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.