Skip to content

Commit

Permalink
Short circuit rememberRetained if the LocalRetainedStateRegistry
Browse files Browse the repository at this point in the history
…isn't set (#1438)

Fixes #1434
  • Loading branch information
stagg authored May 28, 2024
1 parent 6f47c1d commit 39cad58
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Changelog
**Unreleased**
--------------

- **Fix**: Fix `rememberRetained` implicitly requiring `LocalContext` where it used to no-op.

0.22.0
------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.slack.circuit.retained.Continuity
import com.slack.circuit.retained.ContinuityViewModel
import com.slack.circuit.retained.LocalCanRetainChecker
import com.slack.circuit.retained.LocalRetainedStateRegistry
import com.slack.circuit.retained.NoOpRetainedStateRegistry
import com.slack.circuit.retained.continuityRetainedStateRegistry
import com.slack.circuit.retained.rememberCanRetainChecker
import com.slack.circuit.retained.rememberRetained
Expand Down Expand Up @@ -125,6 +126,44 @@ class RetainedSaveableTest {
composeTestRule.onNodeWithTag("superBigData").assertTextEquals("null")
}

@Test
fun saveableIsUsedWhenRetainIsNoop() {
var id = 0
lateinit var data: CacheableData

fun setContent() {
scenario.onActivity { activity ->
activity.setContent {
CompositionLocalProvider(LocalRetainedStateRegistry provides NoOpRetainedStateRegistry) {
data = rememberRetained(saver = CacheableData.Saver) { CacheableData(id++) }
Text(modifier = Modifier.testTag("id"), text = "${data.id}")
Text(modifier = Modifier.testTag("superBigData"), text = "${data.superBigData}")
}
}
}
}

setContent()

// Check initial state is correct
composeTestRule.onNodeWithTag("id").assertTextEquals("0")
composeTestRule.onNodeWithTag("superBigData").assertTextEquals("null")

data.superBigData = "Super big data"
composeTestRule.waitForIdle()

composeTestRule.onNodeWithTag("id").assertTextEquals("0")
composeTestRule.onNodeWithTag("superBigData").assertTextEquals("Super big data")

scenario.recreate()

setContent()

// Retained state is not preserved, but id is
composeTestRule.onNodeWithTag("id").assertTextEquals("0")
composeTestRule.onNodeWithTag("superBigData").assertTextEquals("null")
}

private fun setActivityContent(content: @Composable () -> Unit) {
scenario.onActivity { activity ->
activity.setContent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.runtime.saveable.SaveableStateRegistry
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.SaverScope
import androidx.compose.runtime.saveable.autoSaver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.snapshots.SnapshotMutableState
import androidx.compose.runtime.structuralEqualityPolicy

Expand Down Expand Up @@ -144,7 +145,10 @@ public fun <T : Any> rememberRetained(
): T {
val saveableStateRegistry = LocalSaveableStateRegistry.current
val retainedStateRegistry = LocalRetainedStateRegistry.current

// Short-circuit no-ops
if (retainedStateRegistry === NoOpRetainedStateRegistry) {
return rememberSaveable(inputs = inputs, saver = saver, init = init)
}
val compositeKey = currentCompositeKeyHash
// key is the one provided by the user or the one generated by the compose runtime
val finalKey =
Expand Down

0 comments on commit 39cad58

Please sign in to comment.