1717package com.example.compose.snippets.sideeffects
1818
1919import android.media.Image
20+ import androidx.compose.animation.AnimatedVisibility
2021import androidx.compose.foundation.layout.Box
2122import androidx.compose.foundation.layout.Column
22- import androidx.compose.foundation.layout.fillMaxSize
2323import androidx.compose.foundation.layout.padding
2424import androidx.compose.foundation.lazy.LazyColumn
25- import androidx.compose.foundation.lazy.items
25+ import androidx.compose.foundation.lazy.rememberLazyListState
2626import androidx.compose.material.Button
2727import androidx.compose.material3.Scaffold
2828import androidx.compose.material3.SnackbarHost
@@ -35,18 +35,20 @@ import androidx.compose.runtime.SideEffect
3535import androidx.compose.runtime.State
3636import androidx.compose.runtime.derivedStateOf
3737import androidx.compose.runtime.getValue
38- import androidx.compose.runtime.mutableStateListOf
38+ import androidx.compose.runtime.mutableStateOf
3939import androidx.compose.runtime.produceState
4040import androidx.compose.runtime.remember
4141import androidx.compose.runtime.rememberCoroutineScope
4242import androidx.compose.runtime.rememberUpdatedState
43+ import androidx.compose.runtime.setValue
4344import androidx.compose.ui.Modifier
4445import androidx.compose.ui.platform.LocalLifecycleOwner
4546import androidx.lifecycle.Lifecycle
4647import androidx.lifecycle.LifecycleEventObserver
4748import androidx.lifecycle.LifecycleOwner
4849import com.example.compose.snippets.interop.FirebaseAnalytics
4950import com.example.compose.snippets.interop.User
51+ import com.example.compose.snippets.kotlin.Message
5052import kotlinx.coroutines.delay
5153import kotlinx.coroutines.launch
5254
@@ -236,28 +238,47 @@ sealed class Result<out T> {
236238
237239// [START android_compose_side_effects_derivedstateof]
238240@Composable
239- fun TodoList (highPriorityKeywords : List <String > = listOf("Review ", "Unblock ", "Compose ")) {
241+ // When the messages parameter changes, the MessageList
242+ // composable recomposes. derivedStateOf does not
243+ // affect this recomposition.
244+ fun MessageList (messages : List <Message >) {
245+ Box {
246+ val listState = rememberLazyListState()
240247
241- val todoTasks = remember { mutableStateListOf<String >() }
248+ LazyColumn (state = listState) {
249+ // ...
250+ }
242251
243- // Calculate high priority tasks only when the todoTasks or highPriorityKeywords
244- // change, not on every recomposition
245- val highPriorityTasks by remember(highPriorityKeywords) {
246- derivedStateOf {
247- todoTasks.filter { task ->
248- highPriorityKeywords.any { keyword ->
249- task.contains(keyword)
250- }
252+ // Show the button if the first visible item is past
253+ // the first item. We use a remembered derived state to
254+ // minimize unnecessary compositions
255+ val showButton by remember {
256+ derivedStateOf {
257+ listState.firstVisibleItemIndex > 0
251258 }
252259 }
253- }
254260
255- Box (Modifier .fillMaxSize()) {
256- LazyColumn {
257- items(highPriorityTasks) { /* ... */ }
258- items(todoTasks) { /* ... */ }
261+ AnimatedVisibility (visible = showButton) {
262+ ScrollToTopButton ()
259263 }
260- /* Rest of the UI where users can add elements to the list */
261264 }
262265}
263266// [END android_compose_side_effects_derivedstateof]
267+
268+ @Composable
269+ fun ScrollToTopButton () {
270+ // Button to scroll to the top of list.
271+ }
272+
273+ @Suppress(" CanBeVal" )
274+ @Composable
275+ fun DerivedStateOfWrongUsage () {
276+ // [START android_compose_side_effects_derivedstateof_wrong]
277+ // DO NOT USE. Incorrect usage of derivedStateOf.
278+ var firstName by remember { mutableStateOf(" " ) }
279+ var lastName by remember { mutableStateOf(" " ) }
280+
281+ val fullNameBad by remember { derivedStateOf { " $firstName $lastName " } } // This is bad!!!
282+ val fullNameCorrect = " $firstName $lastName " // This is correct
283+ // [END android_compose_side_effects_derivedstateof_wrong]
284+ }
0 commit comments