Skip to content

Commit b34b694

Browse files
Update Tutorial 8-2, and add Leak Canary to tutorials from 6 to 8
1 parent 4a0303b commit b34b694

File tree

37 files changed

+630
-334
lines changed

37 files changed

+630
-334
lines changed

Tutorial6-1NavigationUI-ViewPager2/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ dependencies {
5959
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6060
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6161

62+
// Leak Canary
63+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
64+
6265
testImplementation 'junit:junit:4.+'
6366
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
6467
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial6-2NavigationUI-ViewPager2-NestedNavhost/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ dependencies {
5959
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6060
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6161

62+
// Leak Canary
63+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
64+
6265
testImplementation 'junit:junit:4.+'
6366
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
6467
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial6-3NavigationUI-ViewPager2-Appbar-NestedNavigation-LiveData/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial6-4NavigationUI-ViewPager2-FragmentToolbar-NestedNavigation/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial6-5NavigationUI-ViewPager2-FragmentToolbar-MixedNavigation/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial6-6NavigationUI-ViewPager2-Appbar-MixedNavigation-ViewModel/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial7-1BNV-ViewPager2-NestedNavigation/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial7-2BNV-ViewPager2-ComplexArchitecture/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ dependencies {
6767
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
6868
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
6969

70+
// Leak Canary
71+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
72+
7073
testImplementation 'junit:junit:4.+'
7174
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7275
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial7-3BNV-ViewPager2-FragmentToolbar-MixedNavigation/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ dependencies {
9191
debugImplementation 'com.readystatesoftware.chuck:library:1.1.0'
9292
releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0'
9393

94+
// Leak Canary
95+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
96+
9497
testImplementation 'junit:junit:4.+'
9598
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
9699
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial8-1DynamicFeatures-Navigation/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ dependencies {
7474
implementation "androidx.navigation:navigation-runtime-ktx:$rootProject.navigationVersion"
7575
implementation "androidx.navigation:navigation-dynamic-features-fragment:$rootProject.navigationVersion"
7676

77+
// Leak Canary
78+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
79+
7780
testImplementation 'junit:junit:4.+'
7881
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
7982
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

Tutorial8-1DynamicFeatures-Navigation/src/main/java/com/smarttoolfactory/tutorial8_1dynamicfeatures_navigation/MainActivity.kt

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class MainActivity : AppCompatActivity() {
3232
override fun onCreate(savedInstanceState: Bundle?) {
3333
super.onCreate(savedInstanceState)
3434

35-
3635
val dataBinding: ActivityMainBinding =
3736
DataBindingUtil.setContentView(this, R.layout.activity_main)
3837

Tutorial8-2DynamicFeatures-ComplexArchitecture/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ dependencies {
9898
debugImplementation 'com.readystatesoftware.chuck:library:1.1.0'
9999
releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0'
100100

101+
// Leak Canary
102+
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
103+
101104
testImplementation 'junit:junit:4.+'
102105
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
103106
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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 com.smarttoolfactory.tutorial8_2dynamicfeatures_complexarchitecture
18+
//
19+
//import android.content.Intent
20+
//import android.util.SparseArray
21+
//import androidx.core.util.forEach
22+
//import androidx.core.util.set
23+
//import androidx.fragment.app.FragmentManager
24+
//import androidx.lifecycle.LiveData
25+
//import androidx.lifecycle.MutableLiveData
26+
//import androidx.navigation.NavController
27+
//import androidx.navigation.fragment.NavHostFragment
28+
//import com.google.android.material.bottomnavigation.BottomNavigationView
29+
//
30+
///**
31+
// * Manages the various graphs needed for a [BottomNavigationView].
32+
// *
33+
// * This sample is a workaround until the Navigation Component supports multiple back stacks.
34+
// */
35+
//fun BottomNavigationView.setupWithDynamicNavController(
36+
// navGraphPair: List<Pair<Int, Int>>,
37+
// fragmentManager: FragmentManager,
38+
// containerId: Int,
39+
// intent: Intent
40+
//): LiveData<NavController> {
41+
//
42+
// // Map of tags
43+
// val graphIdToTagMap = SparseArray<String>()
44+
// // Result. Mutable live data with the selected controlled
45+
// val selectedNavController = MutableLiveData<NavController>()
46+
//
47+
// var firstFragmentGraphId = 0
48+
//
49+
// // First create a NavHostFragment for each NavGraph ID
50+
// navGraphPair.forEachIndexed { index, navGraphPair ->
51+
// val fragmentTag = getFragmentTag(index)
52+
//
53+
// // Find or create the Navigation host fragment
54+
// val navHostFragment = obtainNavHostFragment(
55+
// fragmentManager,
56+
// fragmentTag,
57+
// navGraphPair,
58+
// containerId
59+
// )
60+
//
61+
// // Obtain its id
62+
// val graphId = navHostFragment.navController.graph.id
63+
//
64+
// if (index == 0) {
65+
// firstFragmentGraphId = graphId
66+
// }
67+
//
68+
// // Save to the map
69+
// graphIdToTagMap[graphId] = fragmentTag
70+
//
71+
// // Attach or detach nav host fragment depending on whether it's the selected item.
72+
// if (this.selectedItemId == graphId) {
73+
// // Update livedata with the selected graph
74+
// selectedNavController.value = navHostFragment.navController
75+
// attachNavHostFragment(fragmentManager, navHostFragment, index == 0)
76+
// } else {
77+
// detachNavHostFragment(fragmentManager, navHostFragment)
78+
// }
79+
// }
80+
//
81+
// // Now connect selecting an item with swapping Fragments
82+
// var selectedItemTag = graphIdToTagMap[this.selectedItemId]
83+
// val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
84+
// var isOnFirstFragment = selectedItemTag == firstFragmentTag
85+
//
86+
// // When a navigation item is selected
87+
// setOnNavigationItemSelectedListener { item ->
88+
// // Don't do anything if the state is state has already been saved.
89+
// if (fragmentManager.isStateSaved) {
90+
// false
91+
// } else {
92+
// val newlySelectedItemTag = graphIdToTagMap[item.itemId]
93+
// if (selectedItemTag != newlySelectedItemTag) {
94+
// // Pop everything above the first fragment (the "fixed start destination")
95+
// fragmentManager.popBackStack(
96+
// firstFragmentTag,
97+
// FragmentManager.POP_BACK_STACK_INCLUSIVE
98+
// )
99+
// val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
100+
// as NavHostFragment
101+
//
102+
// // Exclude the first fragment tag because it's always in the back stack.
103+
// if (firstFragmentTag != newlySelectedItemTag) {
104+
// // Commit a transaction that cleans the back stack and adds the first fragment
105+
// // to it, creating the fixed started destination.
106+
// fragmentManager.beginTransaction()
107+
// .attach(selectedFragment)
108+
// .setPrimaryNavigationFragment(selectedFragment)
109+
// .apply {
110+
// // Detach all other Fragments
111+
// graphIdToTagMap.forEach { _, fragmentTagIter ->
112+
// if (fragmentTagIter != newlySelectedItemTag) {
113+
// detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
114+
// }
115+
// }
116+
// }
117+
// .addToBackStack(firstFragmentTag)
118+
// .setCustomAnimations(
119+
// R.anim.nav_default_enter_anim,
120+
// R.anim.nav_default_exit_anim,
121+
// R.anim.nav_default_pop_enter_anim,
122+
// R.anim.nav_default_pop_exit_anim
123+
// )
124+
// .setReorderingAllowed(true)
125+
// .commit()
126+
// }
127+
// selectedItemTag = newlySelectedItemTag
128+
// isOnFirstFragment = selectedItemTag == firstFragmentTag
129+
// selectedNavController.value = selectedFragment.navController
130+
// true
131+
// } else {
132+
// false
133+
// }
134+
// }
135+
// }
136+
//
137+
// // Optional: on item reselected, pop back stack to the destination of the graph
138+
// setupItemReselected(graphIdToTagMap, fragmentManager)
139+
//
140+
// // Handle deep link
141+
// setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)
142+
//
143+
// // Finally, ensure that we update our BottomNavigationView when the back stack changes
144+
// fragmentManager.addOnBackStackChangedListener {
145+
// if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) {
146+
// this.selectedItemId = firstFragmentGraphId
147+
// }
148+
//
149+
// // Reset the graph if the currentDestination is not valid (happens when the back
150+
// // stack is popped after using the back button).
151+
// selectedNavController.value?.let { controller ->
152+
// if (controller.currentDestination == null) {
153+
// controller.navigate(controller.graph.id)
154+
// }
155+
// }
156+
// }
157+
// return selectedNavController
158+
//}
159+
//
160+
//private fun BottomNavigationView.setupDeepLinks(
161+
// navGraphIds: List<Int>,
162+
// fragmentManager: FragmentManager,
163+
// containerId: Int,
164+
// intent: Intent
165+
//) {
166+
// navGraphIds.forEachIndexed { index, navGraphId ->
167+
// val fragmentTag = getFragmentTag(index)
168+
//
169+
// // Find or create the Navigation host fragment
170+
// val navHostFragment = obtainNavHostFragment(
171+
// fragmentManager,
172+
// fragmentTag,
173+
// navGraphId,
174+
// containerId
175+
// )
176+
// // Handle Intent
177+
// if (navHostFragment.navController.handleDeepLink(intent)
178+
// && selectedItemId != navHostFragment.navController.graph.id
179+
// ) {
180+
// this.selectedItemId = navHostFragment.navController.graph.id
181+
// }
182+
// }
183+
//}
184+
//
185+
//private fun BottomNavigationView.setupItemReselected(
186+
// graphIdToTagMap: SparseArray<String>,
187+
// fragmentManager: FragmentManager
188+
//) {
189+
// setOnNavigationItemReselectedListener { item ->
190+
// val newlySelectedItemTag = graphIdToTagMap[item.itemId]
191+
// val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
192+
// as NavHostFragment
193+
// val navController = selectedFragment.navController
194+
// // Pop the back stack to the start destination of the current navController graph
195+
// navController.popBackStack(
196+
// navController.graph.startDestination, false
197+
// )
198+
// }
199+
//}
200+
//
201+
//private fun detachNavHostFragment(
202+
// fragmentManager: FragmentManager,
203+
// navHostFragment: NavHostFragment
204+
//) {
205+
// fragmentManager.beginTransaction()
206+
// .detach(navHostFragment)
207+
// .commitNow()
208+
//}
209+
//
210+
//private fun attachNavHostFragment(
211+
// fragmentManager: FragmentManager,
212+
// navHostFragment: NavHostFragment,
213+
// isPrimaryNavFragment: Boolean
214+
//) {
215+
// fragmentManager.beginTransaction()
216+
// .attach(navHostFragment)
217+
// .apply {
218+
// if (isPrimaryNavFragment) {
219+
// setPrimaryNavigationFragment(navHostFragment)
220+
// }
221+
// }
222+
// .commitNow()
223+
//
224+
//}
225+
//
226+
//private fun obtainNavHostFragment(
227+
// fragmentManager: FragmentManager,
228+
// fragmentTag: String,
229+
// navGraphPair: Pair<Int, Int>,
230+
// containerId: Int
231+
//): NavHostFragment {
232+
// // If the Nav Host fragment exists, return it
233+
// val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
234+
// existingFragment?.let { return it }
235+
//
236+
// // Otherwise, create it and return it.
237+
// val navHostFragment = NavHostFragment.create(navGraphId)
238+
// fragmentManager.beginTransaction()
239+
// .add(containerId, navHostFragment, fragmentTag)
240+
// .commitNow()
241+
// return navHostFragment
242+
//}
243+
//
244+
//private fun FragmentManager.isOnBackStack(backStackName: String): Boolean {
245+
// val backStackCount = backStackEntryCount
246+
// for (index in 0 until backStackCount) {
247+
// if (getBackStackEntryAt(index).name == backStackName) {
248+
// return true
249+
// }
250+
// }
251+
// return false
252+
//}
253+
//
254+
//private fun getFragmentTag(index: Int) = "bottomNavigation#$index"

0 commit comments

Comments
 (0)