1+ /*
2+ * Copyright 2025 The Android Open Source Project
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * https://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ package com.example.compose.snippets.state
18+
19+ import androidx.compose.runtime.Composable
20+ import androidx.compose.runtime.RememberObserver
21+ import androidx.compose.runtime.remember
22+ import kotlinx.coroutines.CoroutineScope
23+ import kotlinx.coroutines.Dispatchers
24+ import kotlinx.coroutines.Job
25+ import kotlinx.coroutines.launch
26+
27+ private object RememberAndRetainObserverSnippets1 {
28+ interface RememberObserver : androidx.compose.runtime.RememberObserver {
29+ override fun onAbandoned () {}
30+ override fun onForgotten () {}
31+ override fun onRemembered () {}
32+ }
33+
34+ // [START android_compose_state_observers_initialize_in_remember]
35+ class MyComposeObject : RememberObserver {
36+ private val job = Job ()
37+ private val coroutineScope = CoroutineScope (Dispatchers .Main + job)
38+
39+ init {
40+ // Not recommended: This will cause work to begin during composition instead of
41+ // with other effects. Move this into onRemembered().
42+ coroutineScope.launch { loadData() }
43+ }
44+
45+ override fun onRemembered () {
46+ // Recommended: Move any cancellable or effect-driven work into the onRemembered
47+ // callback. If implementing RetainObserver, this should go in onRetained.
48+ coroutineScope.launch { loadData() }
49+ }
50+
51+ private suspend fun loadData () { /* ... */ }
52+
53+ // ...
54+ }
55+ // [END android_compose_state_observers_initialize_in_remember]
56+ }
57+
58+ private object RememberAndRetainObserverSnippets2 {
59+ interface RememberObserver : androidx.compose.runtime.RememberObserver {
60+ override fun onAbandoned () {}
61+ override fun onForgotten () {}
62+ override fun onRemembered () {}
63+ }
64+
65+ // [START android_compose_state_observers_teardown_in_forget]
66+ class MyComposeObject : RememberObserver {
67+ private val job = Job ()
68+ private val coroutineScope = CoroutineScope (Dispatchers .Main + job)
69+
70+ // ...
71+
72+ override fun onForgotten () {
73+ // Cancel work launched from onRemembered. If implementing RetainObserver, onRetired
74+ // should cancel work launched from onRetained.
75+ job.cancel()
76+ }
77+
78+ override fun onAbandoned () {
79+ // If any work was launched by the constructor as part of remembering the object,
80+ // you must cancel that work in this callback. For work done as part of the construction
81+ // during retain, this code should will appear in onUnused.
82+ job.cancel()
83+ }
84+ }
85+ // [END android_compose_state_observers_teardown_in_forget]
86+ }
87+
88+ private object RememberAndRetainObserverSnippets3 {
89+ interface RememberObserver : androidx.compose.runtime.RememberObserver {
90+ override fun onAbandoned () {}
91+ override fun onForgotten () {}
92+ override fun onRemembered () {}
93+ }
94+
95+ // [START android_compose_state_observers_private_implementation]
96+ abstract class MyManager
97+
98+ class MyComposeManager : MyManager () {
99+ // Callers that construct this object must manually call initialize and teardown
100+ fun initialize () { /* ...*/ }
101+ fun teardown () { /* ...*/ }
102+ }
103+
104+ @Composable
105+ fun rememberMyManager (): MyManager {
106+ // Protect the RememberObserver implementation by never exposing it outside the library
107+ return remember {
108+ object : RememberObserver {
109+ val manager = MyComposeManager ()
110+ override fun onRemembered () = manager.initialize()
111+ override fun onForgotten () = manager.teardown()
112+ override fun onAbandoned () { /* Nothing to do if manager hasn't initialized */ }
113+ }
114+ }.manager
115+ }
116+ // [END android_compose_state_observers_private_implementation]
117+ }
118+
119+ private object RememberAndRetainObserverSnippets4 {
120+ class Foo : RememberObserver {
121+ override fun onRemembered () {}
122+ override fun onForgotten () {}
123+ override fun onAbandoned () {}
124+ }
125+
126+ class Bar (val foo : Foo )
127+
128+ @Composable fun rememberFoo () = remember { Foo () }
129+
130+ @Composable
131+ fun Snippet () {
132+ // [START android_compose_state_observers_transitive_remember]
133+ val foo: Foo = rememberFoo()
134+
135+ // Acceptable:
136+ val bar: Bar = remember { Bar (foo) }
137+
138+ // Recommended key usage:
139+ val barWithKey: Bar = remember(foo) { Bar (foo) }
140+ // [END android_compose_state_observers_transitive_remember]
141+ }
142+ }
143+
144+ private object RememberAndRetainObserverSnippets5 {
145+ class Foo : RememberObserver {
146+ override fun onRemembered () {}
147+ override fun onForgotten () {}
148+ override fun onAbandoned () {}
149+ }
150+
151+ class Bar (val foo : Foo )
152+
153+ @Composable fun rememberFoo () = remember { Foo () }
154+
155+ // [START android_compose_state_observers_transitive_remember_params]
156+ @Composable
157+ fun MyComposable (
158+ parameter : Foo
159+ ) {
160+ // Acceptable:
161+ val derivedValue = remember { Bar (parameter) }
162+
163+ // Also Acceptable:
164+ val derivedValueWithKey = remember(parameter) { Bar (parameter) }
165+ }
166+ // [END android_compose_state_observers_transitive_remember_params]
167+ }
0 commit comments