Assisted inject approach

Change-Id: I5fba15921520bc83b13601fa82ae71457d875805
av/material3-adaptive-1.1
Alex Vanyo 2 weeks ago
parent 89c408b5c4
commit 9b83e060b1

@ -18,6 +18,7 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler
import androidx.annotation.Keep
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
@ -50,6 +51,7 @@ import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.viewModelFactory
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@ -57,6 +59,9 @@ import androidx.navigation.compose.rememberNavController
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel_Factory
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen
@ -126,28 +131,10 @@ internal fun InterestsListDetailScreen(
val route = selectedTopicId?.let { TopicRoute(id = it) } ?: TopicPlaceholderRoute
mutableStateOf(route)
}
var nestedNavKey by rememberSaveable(
stateSaver = Saver({ it.toString() }, UUID::fromString),
) {
mutableStateOf(UUID.randomUUID())
}
val nestedNavController = key(nestedNavKey) {
rememberNavController()
}
fun onTopicClickShowDetailPane(topicId: String) {
onTopicClick(topicId)
if (listDetailNavigator.isDetailPaneVisible()) {
// If the detail pane was visible, then use the nestedNavController navigate call
// directly
nestedNavController.navigateToTopic(topicId) {
popUpTo<DetailPaneNavHostRoute>()
}
} else {
// Otherwise, recreate the NavHost entirely, and start at the new destination
nestedNavHostStartRoute = TopicRoute(id = topicId)
nestedNavKey = UUID.randomUUID()
}
nestedNavHostStartRoute = TopicRoute(id = topicId)
coroutineScope.launch {
listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
@ -207,22 +194,25 @@ internal fun InterestsListDetailScreen(
}
},
) {
key(nestedNavKey) {
NavHost(
navController = nestedNavController,
startDestination = nestedNavHostStartRoute,
route = DetailPaneNavHostRoute::class,
) {
topicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = {
coroutineScope.launch {
listDetailNavigator.navigateBack()
AnimatedContent(nestedNavHostStartRoute) { route ->
when (route) {
is TopicRoute -> {
TopicScreen(
showBackButton = !listDetailNavigator.isListPaneVisible(),
onBackClick = {
coroutineScope.launch {
listDetailNavigator.navigateBack()
}
},
onTopicClick = ::onTopicClickShowDetailPane,
viewModel = hiltViewModel<TopicViewModel, TopicViewModel.Factory>(
key = route.id,
) { factory ->
factory.create(route.id)
}
},
onTopicClick = ::onTopicClickShowDetailPane,
)
composable<TopicPlaceholderRoute> {
)
}
is TopicPlaceholderRoute -> {
TopicDetailPlaceholder()
}
}

@ -16,10 +16,8 @@
package com.google.samples.apps.nowinandroid.feature.topic
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
@ -29,7 +27,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.result.Result
import com.google.samples.apps.nowinandroid.core.result.asResult
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@ -38,18 +38,14 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class TopicViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
@HiltViewModel(assistedFactory = TopicViewModel.Factory::class)
class TopicViewModel @AssistedInject constructor(
private val userDataRepository: UserDataRepository,
topicsRepository: TopicsRepository,
userNewsResourceRepository: UserNewsResourceRepository,
@Assisted val topicId: String,
) : ViewModel() {
val topicId = savedStateHandle.toRoute<TopicRoute>().id
val topicUiState: StateFlow<TopicUiState> = topicUiState(
topicId = topicId,
userDataRepository = userDataRepository,
@ -89,6 +85,13 @@ class TopicViewModel @Inject constructor(
userDataRepository.setNewsResourceViewed(newsResourceId, viewed)
}
}
@AssistedFactory
interface Factory {
fun create(
topicId: String,
): TopicViewModel
}
}
private fun topicUiState(

@ -18,7 +18,7 @@ androidxHiltNavigationCompose = "1.2.0"
androidxLifecycle = "2.8.7"
androidxMacroBenchmark = "1.3.3"
androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.8.4"
androidxNavigation = "2.8.5"
androidxProfileinstaller = "1.4.1"
androidxTestCore = "1.6.1"
androidxTestExt = "1.2.1"

Loading…
Cancel
Save