[Android] 004. androidx.hilt:hilt-navigation-compose

hiltを使ってViewModelを画面間で引き継いで使う実装をしてみようと思います
NavigationGraphをネストさせてbackstackをhiltViewModel()に渡すことで実現できます

developerの説明
https://developer.android.com/jetpack/compose/libraries#hilt

hiltの依存関係の設定

いつも通りサクッと設定

[versions]
com-google-devtools-ksp = "1.9.20-1.0.14"
hilt = "2.50"
hiltNavigationCompose = "1.2.0-alpha01"

[libraries]
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" }

[plugins]
com-google-devtools-ksp = {id = "com.google.devtools.ksp", version.ref = "com-google-devtools-ksp" }
com-google-dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
plugins {
    alias(libs.plugins.com.google.devtools.ksp) apply false
    alias(libs.plugins.com.google.dagger.hilt.android) apply false
}
plugins {
    alias(libs.plugins.com.google.devtools.ksp)
    alias(libs.plugins.com.google.dagger.hilt.android)
}

dependencies {
    implementation(libs.androidx.hilt.navigation.compose)
    implementation(libs.hilt.android)
    ksp(libs.hilt.compiler)
}

hiltをプロジェクトに適応

いつも通りサクッと追加

/**
 * ```AndroidManifest.xml
 * <application
 *     android:name=".Application"
 * ```
 */
@HiltAndroidApp
class Application : android.app.Application() {
    override fun onCreate() {
        super.onCreate()
    }
}
@AndroidEntryPoint
class MainActivity : ComponentActivity() { ... }

実装

確認用のUIを用意

@HiltViewModel
class AppViewModel @Inject constructor() : ViewModel() {
    var text = ""
}

@Composable
private fun Screen(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    text: String = "",
    vm: AppViewModel = hiltViewModel()
) {
    Column(modifier) {
        Button(onClick = onClick) {
            Text(vm.text + text)
        }
    }
}

@Composable
fun TopScreen(onClick: () -> Unit, vm: AppViewModel) = Screen(onClick, Modifier, "1", vm)
@Composable
fun NextScreen(onClick: () -> Unit, vm: AppViewModel) = Screen(onClick, Modifier, "2", vm)

Navgationを実装
TopScreenでViewModelに指定した”test”がNextScreenにも適応されていることが確認できます
hiltViewModel()にbackstackを渡さない場合は”test”は表示されないです

const val BaseRoute = "Base"
enum class NavDestination {
    Top,
    Next;

    operator fun invoke() = name
}

fun NavGraphBuilder.navGraph(navController: NavController) {
    navigation(startDestination = NavDestination.Top(), route = BaseRoute) {
        NavDestination.entries.forEach { destination ->
            composable(destination()) { backStackEntry ->
                val parentEntry = remember(backStackEntry) {
                    navController.getBackStackEntry(BaseRoute)
                }
                val vm: AppViewModel = hiltViewModel(parentEntry)
                // val vm: AppViewModel = hiltViewModel()

                when (destination) {
                    NavDestination.Top -> {
                        vm.text = "test"
                        TopScreen(onClick = { navController.navigate(NavDestination.Next()) }, vm = vm)
                    }
                    NavDestination.Next -> NextScreen(onClick = { navController.popBackStack() }, vm = vm)
                }
            }
        }
    }
}

@Composable
fun AppContent() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = BaseRoute) {
        navGraph(navController)
    }
}

Android Studio Hedgehog 2023.1.1 Patch 1 built on December 27, 2023