1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.navigation.dynamicfeatures.fragment
18 
19 import android.os.Bundle
20 import androidx.annotation.NavigationRes
21 import androidx.navigation.NavHostController
22 import androidx.navigation.dynamicfeatures.DynamicActivityNavigator
23 import androidx.navigation.dynamicfeatures.DynamicGraphNavigator
24 import androidx.navigation.dynamicfeatures.DynamicIncludeGraphNavigator
25 import androidx.navigation.dynamicfeatures.DynamicInstallManager
26 import androidx.navigation.dynamicfeatures.fragment.ui.DefaultProgressFragment
27 import androidx.navigation.fragment.NavHostFragment
28 import androidx.navigation.plusAssign
29 import com.google.android.play.core.splitinstall.SplitInstallManager
30 import com.google.android.play.core.splitinstall.SplitInstallManagerFactory
31 
32 /** The [NavHostFragment] for dynamic features. */
33 public open class DynamicNavHostFragment : NavHostFragment() {
34 
onCreateNavHostControllernull35     override fun onCreateNavHostController(navHostController: NavHostController) {
36         super.onCreateNavHostController(navHostController)
37 
38         val installManager = DynamicInstallManager(requireContext(), createSplitInstallManager())
39         val navigatorProvider = navHostController.navigatorProvider
40 
41         navigatorProvider += DynamicActivityNavigator(requireActivity(), installManager)
42 
43         val fragmentNavigator =
44             DynamicFragmentNavigator(requireContext(), childFragmentManager, id, installManager)
45         navigatorProvider += fragmentNavigator
46 
47         val graphNavigator = DynamicGraphNavigator(navigatorProvider, installManager)
48         graphNavigator.installDefaultProgressDestination {
49             fragmentNavigator.createDestination().apply {
50                 setClassName(DefaultProgressFragment::class.java.name)
51                 id = R.id.dfn_progress_fragment
52             }
53         }
54         navigatorProvider += graphNavigator
55 
56         navigatorProvider +=
57             DynamicIncludeGraphNavigator(
58                 requireContext(),
59                 navigatorProvider,
60                 navHostController.navInflater,
61                 installManager
62             )
63     }
64 
65     /** Create a new [SplitInstallManager]. */
createSplitInstallManagernull66     protected open fun createSplitInstallManager(): SplitInstallManager =
67         SplitInstallManagerFactory.create(requireContext())
68 
69     /** Companion object for DynamicNavHostFragment */
70     public companion object {
71 
72         /**
73          * Create a new [DynamicNavHostFragment] instance with an inflated {@link NavGraph}
74          * resource.
75          *
76          * @param graphResId Resource id of the navigation graph to inflate.
77          * @param startDestinationArgs Arguments to send to the start destination of the graph.
78          * @return A new DynamicNavHostFragment instance.
79          */
80         @JvmStatic
81         @JvmOverloads
82         public fun create(
83             @NavigationRes graphResId: Int,
84             startDestinationArgs: Bundle? = null
85         ): DynamicNavHostFragment {
86             return DynamicNavHostFragment().apply {
87                 arguments =
88                     if (graphResId != 0 || startDestinationArgs != null) {
89                         Bundle().apply {
90                             if (graphResId != 0) {
91                                 putInt(KEY_GRAPH_ID, graphResId)
92                             }
93                             if (startDestinationArgs != null) {
94                                 putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs)
95                             }
96                         }
97                     } else null
98             }
99         }
100     }
101 }
102