Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[All] Update to collectAsStateWithLifecycle to latest alpha #995

Merged
merged 5 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion JetNews/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ dependencies {
implementation(libs.androidx.lifecycle.viewmodel.savedstate)
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.viewModelCompose)

implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.window)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.example.jetnews.ui.article.ArticleScreen
import com.example.jetnews.ui.home.HomeScreenType.ArticleDetails
import com.example.jetnews.ui.home.HomeScreenType.Feed
Expand All @@ -40,6 +41,7 @@ import com.example.jetnews.ui.home.HomeScreenType.FeedWithArticleDetails
* @param openDrawer (event) request opening the app drawer
* @param snackbarHostState (state) state for the [Scaffold] component on this screen
*/
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun HomeRoute(
homeViewModel: HomeViewModel,
Expand All @@ -48,7 +50,7 @@ fun HomeRoute(
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }
) {
// UiState of the HomeScreen
val uiState by homeViewModel.uiState.collectAsState()
val uiState by homeViewModel.uiState.collectAsStateWithLifecycle()

HomeRoute(
uiState = uiState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
Expand All @@ -69,6 +68,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.constrainHeight
import androidx.compose.ui.unit.constrainWidth
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.example.jetnews.R
import com.example.jetnews.data.Result
import com.example.jetnews.data.interests.InterestSection
Expand Down Expand Up @@ -166,15 +167,16 @@ fun InterestsScreen(
* Remembers the content for each tab on the Interests screen
* gathering application data from [InterestsViewModel]
*/
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent> {
// UiState of the InterestsScreen
val uiState by interestsViewModel.uiState.collectAsState()
val uiState by interestsViewModel.uiState.collectAsStateWithLifecycle()

// Describe the screen sections here since each section needs 2 states and 1 event.
// Pass them to the stateless InterestsScreen using a tabContent.
val topicsSection = TabContent(Sections.Topics) {
val selectedTopics by interestsViewModel.selectedTopics.collectAsState()
val selectedTopics by interestsViewModel.selectedTopics.collectAsStateWithLifecycle()
TabWithSections(
sections = uiState.topics,
selectedTopics = selectedTopics,
Expand All @@ -183,7 +185,7 @@ fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent>
}

val peopleSection = TabContent(Sections.People) {
val selectedPeople by interestsViewModel.selectedPeople.collectAsState()
val selectedPeople by interestsViewModel.selectedPeople.collectAsStateWithLifecycle()
TabWithTopics(
topics = uiState.people,
selectedTopics = selectedPeople,
Expand All @@ -192,7 +194,8 @@ fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent>
}

val publicationSection = TabContent(Sections.Publications) {
val selectedPublications by interestsViewModel.selectedPublications.collectAsState()
val selectedPublications by interestsViewModel.selectedPublications
.collectAsStateWithLifecycle()
TabWithTopics(
topics = uiState.publications,
selectedTopics = selectedPublications,
Expand Down
4 changes: 2 additions & 2 deletions Jetcaster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ Using the example of the home screen in the [`com.example.jetcaster.ui.home`](ap

- The ViewModel is implemented as [`HomeViewModel`][homevm], which exposes a `StateFlow<HomeViewState>` for the UI to observe.
- [`HomeViewState`][homevm] contains the complete view state for the home screen as an [`@Immutable`](https://developer.android.com/reference/kotlin/androidx/compose/runtime/Immutable) `data class`.
- The Home Compose UI in [`Home.kt`][homeui] uses [`HomeViewModel`][homevm], and observes it's [`HomeViewState`][homevm] as Compose [State](https://developer.android.com/reference/kotlin/androidx/compose/runtime/State), using [`collectAsState()`](https://developer.android.com/reference/kotlin/androidx/compose/package-summary#collectasstate):
- The Home Compose UI in [`Home.kt`][homeui] uses [`HomeViewModel`][homevm], and observes it's [`HomeViewState`][homevm] as Compose [State](https://developer.android.com/reference/kotlin/androidx/compose/runtime/State), using [`collectAsStateWithLifecycle()`](https://developer.android.com/reference/kotlin/androidx/lifecycle/compose/package-summary#(kotlinx.coroutines.flow.StateFlow).collectAsStateWithLifecycle(androidx.lifecycle.LifecycleOwner,androidx.lifecycle.Lifecycle.State,kotlin.coroutines.CoroutineContext)):

``` kotlin
val viewModel: HomeViewModel = viewModel()
val viewState by viewModel.state.collectAsState()
val viewState by viewModel.state.collectAsStateWithLifecycle()
```

This pattern is used across the different screens:
Expand Down
1 change: 1 addition & 0 deletions Jetcaster/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ dependencies {

implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.viewModelCompose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation.compose)

implementation(libs.androidx.window)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import androidx.compose.material.icons.filled.Search
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -68,6 +67,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
import com.example.jetcaster.R
Expand All @@ -90,12 +91,13 @@ import java.time.Duration
import java.time.LocalDateTime
import java.time.OffsetDateTime

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun Home(
navigateToPlayer: (String) -> Unit,
viewModel: HomeViewModel = viewModel()
) {
val viewState by viewModel.state.collectAsState()
val viewState by viewModel.state.collectAsStateWithLifecycle()
Surface(Modifier.fillMaxSize()) {
HomeContent(
featuredPodcasts = viewState.featuredPodcasts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import androidx.compose.material.icons.rounded.PlayCircleFilled
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
Expand All @@ -68,6 +67,8 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension.Companion.fillToConstraints
import androidx.constraintlayout.compose.Dimension.Companion.preferredWrapContent
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
import coil.request.ImageRequest
Expand All @@ -85,6 +86,7 @@ import com.example.jetcaster.util.viewModelProviderFactoryOf
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun PodcastCategory(
categoryId: Long,
Expand All @@ -101,7 +103,7 @@ fun PodcastCategory(
factory = viewModelProviderFactoryOf { PodcastCategoryViewModel(categoryId) }
)

val viewState by viewModel.state.collectAsState()
val viewState by viewModel.state.collectAsStateWithLifecycle()

/**
* TODO: reset scroll position when category changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,24 @@ import androidx.compose.material.Tab
import androidx.compose.material.TabPosition
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.jetcaster.data.Category
import com.example.jetcaster.ui.home.category.PodcastCategory
import com.example.jetcaster.ui.theme.Keyline1

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun Discover(
navigateToPlayer: (String) -> Unit,
modifier: Modifier = Modifier
) {
val viewModel: DiscoverViewModel = viewModel()
val viewState by viewModel.state.collectAsState()
val viewState by viewModel.state.collectAsStateWithLifecycle()

val selectedCategory = viewState.selectedCategory

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ import androidx.compose.material.icons.rounded.PlayCircleFilled
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -77,6 +76,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.layout.FoldingFeature
import coil.compose.AsyncImage
import coil.request.ImageRequest
Expand All @@ -94,14 +95,15 @@ import kotlinx.coroutines.flow.StateFlow
/**
* Stateful version of the Podcast player
*/
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun PlayerScreen(
viewModel: PlayerViewModel,
devicePosture: StateFlow<DevicePosture>,
onBackPress: () -> Unit
) {
val uiState = viewModel.uiState
val devicePostureValue by devicePosture.collectAsState()
val devicePostureValue by devicePosture.collectAsStateWithLifecycle()
PlayerScreen(uiState, devicePostureValue, onBackPress)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private val initialMessages = listOf(
),
Message(
"Taylor Brooks",
"@aliconors Take a look at the `Flow.collectAsState()` APIs",
"@aliconors Take a look at the `Flow.collectAsStateWithLifecycle()` APIs",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you updated this

"8:05 PM"
),
Message(
Expand Down
1 change: 1 addition & 0 deletions Jetsnack/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.lifecycle.viewModelCompose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.constraintlayout.compose)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.DeleteForever
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
Expand All @@ -70,6 +69,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ChainStyle
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.jetsnack.R
import com.example.jetsnack.model.OrderLine
Expand All @@ -86,13 +87,14 @@ import com.example.jetsnack.ui.theme.AlphaNearOpaque
import com.example.jetsnack.ui.theme.JetsnackTheme
import com.example.jetsnack.ui.utils.formatPrice

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun Cart(
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier,
viewModel: CartViewModel = viewModel(factory = CartViewModel.provideFactory())
) {
val orderLines by viewModel.orderLines.collectAsState()
val orderLines by viewModel.orderLines.collectAsStateWithLifecycle()
val inspiredByCart = remember { SnackRepo.getInspiredByCart() }
Cart(
orderLines = orderLines,
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ Looking for a sample that has the following features?
* [Jetnews - Window Size Classes](https://github.com/android/compose-samples/blob/69e9d862b5ffb321064364d7883e859db6daeccd/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt#L36)
* [Crane - Window Size Classes](https://github.com/android/compose-samples/blob/e7e8733f9b37d80cdc6e9e05dbabe24ccf20b38f/Crane/app/src/main/java/androidx/compose/samples/crane/home/MainActivity.kt#L72)

## Formatting

To automatically format all samples: Run `./scripts/format.sh`
To check one sample for errors: Navigate to the sample folder and run `./gradlew --init-script buildscripts/init.gradle.kts spotlessCheck`
To format one sample: Navigate to the sample folder and run `./gradlew --init-script buildscripts/init.gradle.kts spotlessApply`

## Updates

To update dependencies to their new stable versions, run:
Expand Down
1 change: 1 addition & 0 deletions Reply/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ dependencies {

implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.viewModelCompose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.navigation.compose)

implementation(libs.androidx.activity.compose)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSiz
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.window.layout.FoldingFeature
Expand All @@ -46,7 +47,7 @@ class MainActivity : ComponentActivity() {

private val viewModel: ReplyHomeViewModel by viewModels()

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class, ExperimentalLifecycleComposeApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand Down Expand Up @@ -79,8 +80,8 @@ class MainActivity : ComponentActivity() {
setContent {
ReplyTheme {
val windowSize = calculateWindowSizeClass(this)
val devicePosture by devicePostureFlow.collectAsState()
val uiState by viewModel.uiState.collectAsState()
val devicePosture by devicePostureFlow.collectAsStateWithLifecycle()
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

ReplyApp(
windowSize = windowSize,
Expand Down