共有ViewModelを各画面で共有するには、共有NavGraphを作成して、そのNavGraph内で画面を遷移させます。
同じNavGraph内で画面を遷移させることにより、共有ViewModelのスコープも同じになります。
共有NavGraphは親となるモジュール内に作成しますが、子となるモジュールから共有NavGraph名を参照しますので、循環依存となってしまいます。
循環依存を回避するため、別途ナビゲーションモジュールを作成し、共有NavGraph名だけをナビゲーションモジュールに持たせることにします。
共通UIモジュールの作成と同様に、トップディレクトリで:feature:depart:navigationを作成し、javaディレクトリ名の変更、および、サンプルテストクラスの削除を行います。
:feature:depart:navigationモジュールのbuild.gradle.ktsにビルドプラグインを適用します。
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
id("build.logic.library.configure")
}
android {
namespace = "jp.co.progress_llc.portal.feature.depart.navigation"
compileSdk {
version = release(36)
}
defaultConfig {
minSdk = 28
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
適用後、『Sync Now』で内容をプロジェクトに反映させます。
:feature:depart:navigationモジュールに共有NavGraph名を定義するDepartSharedNavGraphName.ktを作成します。
package jp.co.progress_llc.portal.feature.depart.navigation const val DEPART_ROUTE_EDIT = "depart_route_edit"
共有NavGraphの作成で必要な依存ライブラリを親モジュール:feature:depart:routeのbuild.gradle.ktsに追記します。
:
dependencies {
:
implementation(project(":feature:depart:navigation"))
:
}
追記後、『Sync Now』で内容をプロジェクトに反映させます。
共有するViewModelを持つ画面のNavGraphをまとめたDepartRouteEditNavGraph.ktを、親となる:feature:depart:routeモジュールのnavigationディレクトリ(パッケージ)に作成します。
package jp.co.progress_llc.portal.feature.depart.route.navigation
import androidx.navigation.NavGraphBuilder
import androidx.navigation.navigation
import jp.co.progress_llc.portal.feature.depart.navigation.DEPART_ROUTE_EDIT
fun NavGraphBuilder.departRouteEditNavGraph() {
navigation(
startDestination = DEPART_ROUTE,
route = DEPART_ROUTE_EDIT
) {
departRouteNavGraph()
}
}
:feature:depart:routeモジュールのdiディレクトリ(パッケージ)直下にDepartRouteEditNavGraphModule.ktを作成し、共有NavGraphをDI(Hilt)に登録します。
package jp.co.progress_llc.portal.feature.depart.route.di
import androidx.navigation.NavGraphBuilder
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet
import jp.co.progress_llc.portal.feature.depart.route.navigation.departRouteEditNavGraph
@Module
@InstallIn(SingletonComponent::class)
object DepartRouteEditNavGraphModule {
@Provides
@IntoSet
fun provideDepartEditRouteNavGraph(): NavGraphBuilder.() -> Unit = {
departRouteEditNavGraph()
}
}
外部モジュールが経路一覧編集画面に直接遷移すると、共有ViewModelのスコープを正しく管理できなくなるため、外部モジュールに対して経路一覧編集画面のNavGraphを隠蔽して、経路一覧編集画面に直接遷移できないようにします。
: const val DEPART_ROUTE = "depart_route" internal const val DEPART_ROUTE = "depart_route" :
発車予定のホーム画面は、経路一覧編集画面に直接遷移していますので、共有NavGraphに遷移するように変更します。
共有NavGraphの名前を管理しているモジュールを:feature:depart:homeの依存に追記します。
:
dependencies {
:
implementation(project(":feature:depart:navigation"))
}
発車予定のホーム画面の遷移先を共有NavGraphに変更します。
:
import jp.co.progress_llc.portal.feature.depart.route.navigation.DEPART_ROUTE
import jp.co.progress_llc.portal.feature.depart.navigation.DEPART_ROUTE_EDIT
:
fun DepartHomeScreen() {
:
CustomExposedDropdownMenuBox(
:
onAdditionalItemClick = { navController.navigate(DEPART_ROUTE) }
onAdditionalItemClick = { navController.navigate(DEPART_ROUTE_EDIT) }
:
発車予定のホーム画面のNavGraphも変更します。
:
import jp.co.progress_llc.portal.feature.depart.route.navigation.departRouteNavGraph
import jp.co.progress_llc.portal.feature.depart.route.navigation.departRouteEditNavGraph
:
fun NavGraphBuilder.departHomeNavGraph() {
:
departRouteNavGraph()
departRouteEditNavGraph()
}