DEV Community

myougaTheAxo
myougaTheAxo

Posted on

State Preservation/Restoration Complete Guide — rememberSaveable/SavedStateHandle/Process Death

What You'll Learn

State Preservation/Restoration(rememberSaveable、SavedStateHandle、プロセス死Support、Custom Saver、Navigation引数)を解説します。


remember vs rememberSaveable

@Composable
fun StateComparison() {
    // ❌ remember: Lost on screen rotation
    var count1 by remember { mutableIntStateOf(0) }

    // ✅ rememberSaveable: Persists through screen rotation and process death
    var count2 by rememberSaveable { mutableIntStateOf(0) }

    Column(Modifier.padding(16.dp)) {
        Text("remember: $count1")
        Text("rememberSaveable: $count2")
        Button(onClick = { count1++; count2++ }) { Text("Increment") }
    }
}
Enter fullscreen mode Exit fullscreen mode

Custom Saver

data class EditState(
    val title: String,
    val content: String,
    val isDraft: Boolean
)

val EditStateSaver = run {
    val titleKey = "title"
    val contentKey = "content"
    val isDraftKey = "isDraft"

    mapSaver(
        save = { mapOf(titleKey to it.title, contentKey to it.content, isDraftKey to it.isDraft) },
        restore = { EditState(it[titleKey] as String, it[contentKey] as String, it[isDraftKey] as Boolean) }
    )
}

@Composable
fun EditScreen() {
    var editState by rememberSaveable(stateSaver = EditStateSaver) {
        mutableStateOf(EditState("", "", true))
    }

    Column(Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = editState.title,
            onValueChange = { editState = editState.copy(title = it) },
            label = { Text("タイトル") }
        )
        OutlinedTextField(
            value = editState.content,
            onValueChange = { editState = editState.copy(content = it) },
            label = { Text("内容") },
            modifier = Modifier.height(200.dp)
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

SavedStateHandle (ViewModel)

@HiltViewModel
class EditViewModel @Inject constructor(
    private val savedStateHandle: SavedStateHandle,
    private val repository: ArticleRepository
) : ViewModel() {

    // SavedStateHandle で自動保存/復元
    val title = savedStateHandle.getStateFlow("title", "")
    val content = savedStateHandle.getStateFlow("content", "")

    fun updateTitle(value: String) {
        savedStateHandle["title"] = value
    }

    fun updateContent(value: String) {
        savedStateHandle["content"] = value
    }

    fun save() {
        viewModelScope.launch {
            repository.save(Article(title = title.value, content = content.value))
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Saving List State

@Composable
fun ListWithSavedScroll() {
    val listState = rememberLazyListState() // 自動でスクロール位置保存

    LazyColumn(state = listState) {
        items(100) { index ->
            Text("Item $index", Modifier.padding(16.dp))
        }
    }
}

// Saving Multi-Select State
@Composable
fun MultiSelectList(items: List<Item>) {
    var selectedIds by rememberSaveable {
        mutableStateOf(setOf<String>())
    }

    LazyColumn {
        items(items, key = { it.id }) { item ->
            ListItem(
                headlineContent = { Text(item.title) },
                leadingContent = {
                    Checkbox(
                        checked = item.id in selectedIds,
                        onCheckedChange = { checked ->
                            selectedIds = if (checked) selectedIds + item.id
                                else selectedIds - item.id
                        }
                    )
                }
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Summary

手法 スコープ 用途
remember Recomposition 一時的な状態
rememberSaveable Configuration変更 UI状態
SavedStateHandle プロセス死 ViewModel状態
DataStore 永続 ユーザー設定
  • rememberSaveableで画面回転・プロセス死を生き延びる
  • mapSaver/listSaverでカスタム型を保存
  • SavedStateHandleでViewModelの状態を自動保存
  • LazyListStateはスクロール位置を自動保持

8種類のAndroidAppTemplates(状態管理Pre-designed)を公開しています。

Template ListGumroad

Related Articles:


Ready-Made Android App Templates

8 production-ready Android app templates with Jetpack Compose, MVVM, Hilt, and Material 3.

Browse templatesGumroad

Top comments (0)