具有架构组件的多模块导航
Multi-module Navigation with Architecture Components
所以我在当前的应用程序中为我的模块采用了这种结构。
我还没有找到任何关于多模块导航的官方文档,但我发现了这个 article 关于这个所以我的 gradle 文件是这样的:
功能 1 - 详细信息
...
implementation project(":base")
implementation project(":feature-2-detail")
...
功能 2 - 详细信息
...
implementation project(":base")
implementation project(":feature-1-detail")
...
功能 3 - 详细信息
...
implementation project(":base")
implementation project(":feature-1-detail")
...
这是我的导航图:
功能 1 - 详细信息
<navigation ...
android:id="@+id/graph_feature_1_id">
<include app:graph="@navigation/graph_feature_2" />
<fragment ...
android:id="@+id/nav_feature_1">
<action ...
app:destination="@+id/graph_feature_2_id" />
</fragment>
</navigation>
功能 2 - 详细信息
<navigation ...
android:id="@+id/graph_feature_2_id">
<include app:graph="@navigation/graph_feature_1" />
<fragment ...
android:id="@+id/nav_feature_2">
<action ...
app:destination="@+id/graph_feature_1_id" />
</fragment>
</navigation>
功能 3 - 详细信息
<navigation ...
android:id="@+id/graph_feature_3_id">
<include app:graph="@navigation/graph_feature_1" />
<fragment ...
android:id="@+id/nav_feature_3">
<action ...
app:destination="@+id/graph_feature_1_id" />
</fragment>
</navigation>
所以一切都适用于这种设置,但这里的问题是要将模块连接到另一个模块,我们必须将其他功能添加为当前功能的依赖项。就像我的情况一样,Feature 1 - Detail 可以转到 Feature 2 - Detail 反之亦然,这样做让我在 gradle。
还有其他方法可以做多模块导航吗?我试过使用深层链接但无济于事。
如有任何帮助,我们将不胜感激!谢谢!
当您在基本特征中明确声明每个特征导航图 ID 时,可以删除所有 Gradle 特征间依赖性。我对这个解决方案不是 100% 满意,因为这些 ID 创建 "hidden" 功能间依赖性,但除此之外它工作正常。
以下是此设置的关键部分:
:app
build.gradle
dependencies {
implementation project(':features:feature-base')
implementation project(':features:feature-one')
implementation project(':features:feature-two')
}
:features:feature-base
build.gradle
dependencies {
application project(':app')
feature project(':features:feature-one')
feature project(':features:feature-two')
}
navigation/feature_base_nav_graph.xml
<navigation ...>
<include app:graph="@navigation/feature_one_nav_graph" />
<include app:graph="@navigation/feature_two_nav_graph" />
</navigation>
values/feature_base_ids.xml
<resources>
<item name="feature_one_nav_graph" type="id" />
<item name="feature_two_nav_graph" type="id" />
</resources>
:features:feature-one
build.gradle
dependencies {
implementation project(':features:feature-base')
}
navigation/feature_one_nav_graph.xml
<navigation
android:id="@id/feature_one_nav_graph"
...>
<fragment
android:id="@+id/oneFragment"
...>
<action
android:id="@+id/navigateToFeatureTwo"
app:destination="@id/feature_two_nav_graph"
... />
</fragment>
</navigation>
导航
findNavController().navigate(R.id.navigateToFeatureTwo)
:features:feature-two
build.gradle
dependencies {
implementation project(':features:feature-base')
}
navigation/feature_two_nav_graph.xml
<navigation
android:id="@id/feature_two_nav_graph"
...>
<fragment
android:id="@+id/twoFragment"
...>
<action
android:id="@+id/navigateToFeatureOne"
app:destination="@id/feature_one_nav_graph"
... />
</fragment>
</navigation>
导航
findNavController().navigate(R.id.navigateToFeatureOne)
一种可能有用的方法是创建一个全新的独立模块(例如“:navigation”模块)并将所有 navigation.xml 文件从所有其他模块移动到它。然后我们依赖于所有其他需要导航相关内容的模块中的新 (":navigation") 模块,我们将能够访问它的 R.navigation 或生成的参数 classes 等。
由于新的 (":navigation") 模块不知道项目中的任何其他内容 IDE 会将任何片段标记为红色,activity 和其他 class 我们在 navigation.xml 文件中使用,这些文件是在其他模块外部定义的,但只要我们使用完整的 class 名称(com.exampel.MyFragment),它就会编译并工作。
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph_id"
app:startDestination="@id/some_navigation_id">
<fragment
android:id="@+id/some_navigation_id"
android:name="com.exampel.MyFragment".../>
// com.exampel.MyFragment will be marked red since IDE can't link it
// to the existing class because it is in the other module
这会创建 "hidden" 对我们想要导航到的所有 class 的依赖,我们需要知道 class 名称和潜在的参数,我们必须维护它手动但它允许我们轻松地在独立模块中分离导航。
这已经过去一年了,但库现在可以支持这个确切的用例!从 2.1.0-alpha03 开始,我们可以通过深度 link URI 进行导航。
与其将功能作为实现细节添加到彼此,不如让它们彼此不知情,并使用深度 link 导航。
功能 1 - 详细信息 - build.gradle
dependencies {
implementation project(':base')
}
与功能 2 - 详细信息 相同。不需要它知道其他模块。
要进行模块间导航,我们必须首先定义深度 link,以便通过 deepLink
标签导航到该目的地。
功能 1 - 详细信息 - 导航图
<navigation ...
android:id="@+id/graph_feature_1_detail_id">
<fragment ...
android:id="@+id/nav_feature_1_detail">
<deepLink app:uri="myApp://feature1detail"/>
</fragment>
</navigation>
功能 2 - 详细信息 - 导航图
<navigation ...
android:id="@+id/graph_feature_2_detail_id">
<fragment ...
android:id="@+id/nav_feature_2_detail">
<deepLink app:uri="myApp://feature2detail"/>
</fragment>
</navigation>
现在我们已经设置了 URI 的深度 links,我们可以直接在 NavController
中使用它
所以在 Feature 1 - Detail 的片段中,也许是点击按钮?任何你必须执行导航的地方
class Feature1DetailFragment {
fun onViewCreated(...) {
...
view.setOnClickListener {
val uri = Uri.parse("myApp://feature2detail")
findNavController().navigate(uri)
}
}
}
并且在功能 2 - 详细信息、
class Feature2DetailFragment {
fun onViewCreated(...) {
...
view.setOnClickListener {
val uri = Uri.parse("myApp://feature1detail")
findNavController().navigate(uri)
}
}
}
瞧!模块间导航。
在撰写本文时,最新的稳定版本是 2.1.0-rc01
。
虽然我还没有在更复杂的项目上尝试过,但我喜欢这个库,我希望看到这个库更加成熟!
我为此创建了一个 Medium article。你可以看看它。干杯!
所以我在当前的应用程序中为我的模块采用了这种结构。
我还没有找到任何关于多模块导航的官方文档,但我发现了这个 article 关于这个所以我的 gradle 文件是这样的:
功能 1 - 详细信息
...
implementation project(":base")
implementation project(":feature-2-detail")
...
功能 2 - 详细信息
...
implementation project(":base")
implementation project(":feature-1-detail")
...
功能 3 - 详细信息
...
implementation project(":base")
implementation project(":feature-1-detail")
...
这是我的导航图:
功能 1 - 详细信息
<navigation ...
android:id="@+id/graph_feature_1_id">
<include app:graph="@navigation/graph_feature_2" />
<fragment ...
android:id="@+id/nav_feature_1">
<action ...
app:destination="@+id/graph_feature_2_id" />
</fragment>
</navigation>
功能 2 - 详细信息
<navigation ...
android:id="@+id/graph_feature_2_id">
<include app:graph="@navigation/graph_feature_1" />
<fragment ...
android:id="@+id/nav_feature_2">
<action ...
app:destination="@+id/graph_feature_1_id" />
</fragment>
</navigation>
功能 3 - 详细信息
<navigation ...
android:id="@+id/graph_feature_3_id">
<include app:graph="@navigation/graph_feature_1" />
<fragment ...
android:id="@+id/nav_feature_3">
<action ...
app:destination="@+id/graph_feature_1_id" />
</fragment>
</navigation>
所以一切都适用于这种设置,但这里的问题是要将模块连接到另一个模块,我们必须将其他功能添加为当前功能的依赖项。就像我的情况一样,Feature 1 - Detail 可以转到 Feature 2 - Detail 反之亦然,这样做让我在 gradle。
还有其他方法可以做多模块导航吗?我试过使用深层链接但无济于事。
如有任何帮助,我们将不胜感激!谢谢!
当您在基本特征中明确声明每个特征导航图 ID 时,可以删除所有 Gradle 特征间依赖性。我对这个解决方案不是 100% 满意,因为这些 ID 创建 "hidden" 功能间依赖性,但除此之外它工作正常。
以下是此设置的关键部分:
:app
build.gradle
dependencies {
implementation project(':features:feature-base')
implementation project(':features:feature-one')
implementation project(':features:feature-two')
}
:features:feature-base
build.gradle
dependencies {
application project(':app')
feature project(':features:feature-one')
feature project(':features:feature-two')
}
navigation/feature_base_nav_graph.xml
<navigation ...>
<include app:graph="@navigation/feature_one_nav_graph" />
<include app:graph="@navigation/feature_two_nav_graph" />
</navigation>
values/feature_base_ids.xml
<resources>
<item name="feature_one_nav_graph" type="id" />
<item name="feature_two_nav_graph" type="id" />
</resources>
:features:feature-one
build.gradle
dependencies {
implementation project(':features:feature-base')
}
navigation/feature_one_nav_graph.xml
<navigation
android:id="@id/feature_one_nav_graph"
...>
<fragment
android:id="@+id/oneFragment"
...>
<action
android:id="@+id/navigateToFeatureTwo"
app:destination="@id/feature_two_nav_graph"
... />
</fragment>
</navigation>
导航
findNavController().navigate(R.id.navigateToFeatureTwo)
:features:feature-two
build.gradle
dependencies {
implementation project(':features:feature-base')
}
navigation/feature_two_nav_graph.xml
<navigation
android:id="@id/feature_two_nav_graph"
...>
<fragment
android:id="@+id/twoFragment"
...>
<action
android:id="@+id/navigateToFeatureOne"
app:destination="@id/feature_one_nav_graph"
... />
</fragment>
</navigation>
导航
findNavController().navigate(R.id.navigateToFeatureOne)
一种可能有用的方法是创建一个全新的独立模块(例如“:navigation”模块)并将所有 navigation.xml 文件从所有其他模块移动到它。然后我们依赖于所有其他需要导航相关内容的模块中的新 (":navigation") 模块,我们将能够访问它的 R.navigation 或生成的参数 classes 等。
由于新的 (":navigation") 模块不知道项目中的任何其他内容 IDE 会将任何片段标记为红色,activity 和其他 class 我们在 navigation.xml 文件中使用,这些文件是在其他模块外部定义的,但只要我们使用完整的 class 名称(com.exampel.MyFragment),它就会编译并工作。
<?xml version="1.0" encoding="utf-8"?>
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph_id"
app:startDestination="@id/some_navigation_id">
<fragment
android:id="@+id/some_navigation_id"
android:name="com.exampel.MyFragment".../>
// com.exampel.MyFragment will be marked red since IDE can't link it
// to the existing class because it is in the other module
这会创建 "hidden" 对我们想要导航到的所有 class 的依赖,我们需要知道 class 名称和潜在的参数,我们必须维护它手动但它允许我们轻松地在独立模块中分离导航。
这已经过去一年了,但库现在可以支持这个确切的用例!从 2.1.0-alpha03 开始,我们可以通过深度 link URI 进行导航。
与其将功能作为实现细节添加到彼此,不如让它们彼此不知情,并使用深度 link 导航。
功能 1 - 详细信息 - build.gradle
dependencies {
implementation project(':base')
}
与功能 2 - 详细信息 相同。不需要它知道其他模块。
要进行模块间导航,我们必须首先定义深度 link,以便通过 deepLink
标签导航到该目的地。
功能 1 - 详细信息 - 导航图
<navigation ...
android:id="@+id/graph_feature_1_detail_id">
<fragment ...
android:id="@+id/nav_feature_1_detail">
<deepLink app:uri="myApp://feature1detail"/>
</fragment>
</navigation>
功能 2 - 详细信息 - 导航图
<navigation ...
android:id="@+id/graph_feature_2_detail_id">
<fragment ...
android:id="@+id/nav_feature_2_detail">
<deepLink app:uri="myApp://feature2detail"/>
</fragment>
</navigation>
现在我们已经设置了 URI 的深度 links,我们可以直接在 NavController
所以在 Feature 1 - Detail 的片段中,也许是点击按钮?任何你必须执行导航的地方
class Feature1DetailFragment {
fun onViewCreated(...) {
...
view.setOnClickListener {
val uri = Uri.parse("myApp://feature2detail")
findNavController().navigate(uri)
}
}
}
并且在功能 2 - 详细信息、
class Feature2DetailFragment {
fun onViewCreated(...) {
...
view.setOnClickListener {
val uri = Uri.parse("myApp://feature1detail")
findNavController().navigate(uri)
}
}
}
瞧!模块间导航。
在撰写本文时,最新的稳定版本是 2.1.0-rc01
。
虽然我还没有在更复杂的项目上尝试过,但我喜欢这个库,我希望看到这个库更加成熟!
我为此创建了一个 Medium article。你可以看看它。干杯!