├── DonutTracker ├── ConditionalNavigation │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ └── OneTimeFlowTest.kt │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── Notifier.kt │ │ │ │ ├── UserPreferencesRepository.kt │ │ │ │ ├── coffee │ │ │ │ ├── CoffeeEntryDialogFragment.kt │ │ │ │ ├── CoffeeEntryViewModel.kt │ │ │ │ ├── CoffeeList.kt │ │ │ │ ├── CoffeeListAdapter.kt │ │ │ │ ├── CoffeeListViewModel.kt │ │ │ │ └── CoffeeViewModelFactory.kt │ │ │ │ ├── donut │ │ │ │ ├── DonutEntryDialogFragment.kt │ │ │ │ ├── DonutEntryViewModel.kt │ │ │ │ ├── DonutList.kt │ │ │ │ ├── DonutListAdapter.kt │ │ │ │ ├── DonutListViewModel.kt │ │ │ │ └── DonutViewModelFactory.kt │ │ │ │ ├── model │ │ │ │ ├── Coffee.kt │ │ │ │ └── Donut.kt │ │ │ │ ├── setup │ │ │ │ ├── SelectionFragment.kt │ │ │ │ └── SelectionViewModel.kt │ │ │ │ └── storage │ │ │ │ ├── CoffeeDao.kt │ │ │ │ ├── DonutDao.kt │ │ │ │ └── SnackDatabase.kt │ │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── coffee_cup.xml │ │ │ ├── donut_with_sprinkles.xml │ │ │ ├── ic_clear_24px.xml │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout-w960dp │ │ │ └── activity_main.xml │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── coffee_entry_dialog.xml │ │ │ ├── coffee_item.xml │ │ │ ├── coffee_list.xml │ │ │ ├── donut_entry_dialog.xml │ │ │ ├── donut_item.xml │ │ │ ├── donut_list.xml │ │ │ └── fragment_selection.xml │ │ │ ├── menu │ │ │ ├── bottom_nav_menu.xml │ │ │ ├── menu_main.xml │ │ │ └── nav_drawer_menu.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── navigation │ │ │ └── nav_graph.xml │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ ├── xml-v25 │ │ │ └── shortcuts.xml │ │ │ └── xml │ │ │ ├── preferences.xml │ │ │ └── shortcuts.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── screenshot.png │ ├── settings.gradle │ └── versions.gradle ├── FeatureModules │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ └── OneTimeFlowTest.kt │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── Notifier.kt │ │ │ │ ├── ProgressFragment.kt │ │ │ │ ├── UserPreferencesRepository.kt │ │ │ │ ├── donut │ │ │ │ ├── DonutEntryDialogFragment.kt │ │ │ │ ├── DonutEntryViewModel.kt │ │ │ │ ├── DonutList.kt │ │ │ │ ├── DonutListAdapter.kt │ │ │ │ ├── DonutListViewModel.kt │ │ │ │ └── DonutViewModelFactory.kt │ │ │ │ └── setup │ │ │ │ ├── SelectionFragment.kt │ │ │ │ └── SelectionViewModel.kt │ │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── coffee_cup.xml │ │ │ ├── donut_with_sprinkles.xml │ │ │ ├── ic_clear_24px.xml │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout-w960dp │ │ │ └── activity_main.xml │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── donut_entry_dialog.xml │ │ │ ├── donut_item.xml │ │ │ ├── donut_list.xml │ │ │ ├── fragment_progress.xml │ │ │ └── fragment_selection.xml │ │ │ ├── menu │ │ │ ├── bottom_nav_menu.xml │ │ │ ├── menu_main.xml │ │ │ └── nav_drawer_menu.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── navigation │ │ │ └── nav_graph.xml │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ ├── xml-v25 │ │ │ └── shortcuts.xml │ │ │ └── xml │ │ │ ├── preferences.xml │ │ │ └── shortcuts.xml │ ├── build.gradle │ ├── coffee │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ └── coffee │ │ │ │ ├── CoffeeEntryDialogFragment.kt │ │ │ │ ├── CoffeeEntryViewModel.kt │ │ │ │ ├── CoffeeList.kt │ │ │ │ ├── CoffeeListAdapter.kt │ │ │ │ ├── CoffeeListViewModel.kt │ │ │ │ └── CoffeeViewModelFactory.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ └── coffee_cup.xml │ │ │ ├── layout │ │ │ ├── coffee_entry_dialog.xml │ │ │ ├── coffee_item.xml │ │ │ └── coffee_list.xml │ │ │ ├── navigation │ │ │ └── coffee_graph.xml │ │ │ └── values │ │ │ ├── dimens.xml │ │ │ └── strings.xml │ ├── core │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── android │ │ │ └── samples │ │ │ └── donuttracker │ │ │ └── core │ │ │ ├── model │ │ │ ├── Coffee.kt │ │ │ └── Donut.kt │ │ │ └── storage │ │ │ ├── CoffeeDao.kt │ │ │ ├── DonutDao.kt │ │ │ └── SnackDatabase.kt │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── screenshot.png │ ├── settings.gradle │ └── versions.gradle ├── NavigationUI │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── android │ │ │ │ └── samples │ │ │ │ └── donuttracker │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── Notifier.kt │ │ │ │ ├── coffee │ │ │ │ ├── CoffeeEntryDialogFragment.kt │ │ │ │ ├── CoffeeEntryViewModel.kt │ │ │ │ ├── CoffeeList.kt │ │ │ │ ├── CoffeeListAdapter.kt │ │ │ │ ├── CoffeeListViewModel.kt │ │ │ │ └── CoffeeViewModelFactory.kt │ │ │ │ ├── donut │ │ │ │ ├── DonutEntryDialogFragment.kt │ │ │ │ ├── DonutEntryViewModel.kt │ │ │ │ ├── DonutList.kt │ │ │ │ ├── DonutListAdapter.kt │ │ │ │ ├── DonutListViewModel.kt │ │ │ │ └── DonutViewModelFactory.kt │ │ │ │ ├── model │ │ │ │ ├── Coffee.kt │ │ │ │ └── Donut.kt │ │ │ │ ├── setup │ │ │ │ └── SelectionFragment.kt │ │ │ │ └── storage │ │ │ │ ├── CoffeeDao.kt │ │ │ │ ├── DonutDao.kt │ │ │ │ └── SnackDatabase.kt │ │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ ├── coffee_cup.xml │ │ │ ├── donut_with_sprinkles.xml │ │ │ ├── ic_clear_24px.xml │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout-w960dp │ │ │ └── activity_main.xml │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── coffee_entry_dialog.xml │ │ │ ├── coffee_item.xml │ │ │ ├── coffee_list.xml │ │ │ ├── donut_entry_dialog.xml │ │ │ ├── donut_item.xml │ │ │ ├── donut_list.xml │ │ │ └── fragment_selection.xml │ │ │ ├── menu │ │ │ ├── bottom_nav_menu.xml │ │ │ ├── menu_main.xml │ │ │ └── nav_drawer_menu.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── navigation │ │ │ └── nav_graph.xml │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ │ ├── xml-v25 │ │ │ └── shortcuts.xml │ │ │ └── xml │ │ │ └── shortcuts.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── screenshot.png │ ├── settings.gradle │ └── versions.gradle └── NestedGraphs_Include │ ├── .gitignore │ ├── README.md │ ├── app │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── android │ │ │ └── samples │ │ │ └── donuttracker │ │ │ └── OneTimeFlowTest.kt │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── android │ │ │ └── samples │ │ │ └── donuttracker │ │ │ ├── MainActivity.kt │ │ │ ├── Notifier.kt │ │ │ ├── UserPreferencesRepository.kt │ │ │ ├── donut │ │ │ ├── DonutEntryDialogFragment.kt │ │ │ ├── DonutEntryViewModel.kt │ │ │ ├── DonutList.kt │ │ │ ├── DonutListAdapter.kt │ │ │ ├── DonutListViewModel.kt │ │ │ └── DonutViewModelFactory.kt │ │ │ └── setup │ │ │ ├── SelectionFragment.kt │ │ │ └── SelectionViewModel.kt │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── coffee_cup.xml │ │ ├── donut_with_sprinkles.xml │ │ ├── ic_clear_24px.xml │ │ └── ic_launcher_background.xml │ │ ├── layout-w960dp │ │ └── activity_main.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── donut_entry_dialog.xml │ │ ├── donut_item.xml │ │ ├── donut_list.xml │ │ └── fragment_selection.xml │ │ ├── menu │ │ ├── bottom_nav_menu.xml │ │ ├── menu_main.xml │ │ └── nav_drawer_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ ├── xml-v25 │ │ └── shortcuts.xml │ │ └── xml │ │ ├── preferences.xml │ │ └── shortcuts.xml │ ├── build.gradle │ ├── coffee │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── android │ │ │ └── samples │ │ │ └── donuttracker │ │ │ └── coffee │ │ │ ├── CoffeeEntryDialogFragment.kt │ │ │ ├── CoffeeEntryViewModel.kt │ │ │ ├── CoffeeList.kt │ │ │ ├── CoffeeListAdapter.kt │ │ │ ├── CoffeeListViewModel.kt │ │ │ └── CoffeeViewModelFactory.kt │ │ └── res │ │ ├── drawable │ │ └── coffee_cup.xml │ │ ├── layout │ │ ├── coffee_entry_dialog.xml │ │ ├── coffee_item.xml │ │ └── coffee_list.xml │ │ ├── navigation │ │ └── coffee_graph.xml │ │ └── values │ │ ├── dimens.xml │ │ └── strings.xml │ ├── core │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── android │ │ └── samples │ │ └── donuttracker │ │ └── core │ │ ├── model │ │ ├── Coffee.kt │ │ └── Donut.kt │ │ └── storage │ │ ├── CoffeeDao.kt │ │ ├── DonutDao.kt │ │ └── SnackDatabase.kt │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── screenshot.png │ ├── settings.gradle │ └── versions.gradle ├── LICENSE.md ├── README.md └── contributing.md /DonutTracker/ConditionalNavigation/.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | # Mac files 5 | .DS_Store 6 | # files for the dex VM 7 | *.dex 8 | # Java class files 9 | *.class 10 | # generated files 11 | bin/ 12 | gen/ 13 | # Ignore gradle files 14 | .gradle/ 15 | build/ 16 | # Local configuration file (sdk path, etc) 17 | local.properties 18 | # Proguard folder generated by Eclipse 19 | proguard/ 20 | proguard-project.txt 21 | # Eclipse files 22 | .project 23 | .classpath 24 | .settings/ 25 | # Android Studio/IDEA 26 | *.iml 27 | .idea -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/README.md: -------------------------------------------------------------------------------- 1 | MAD Skills Navigation Sample (Donut Tracker) 2 | ============================================== 3 | 4 | This sample shows the features of Navigation component highlighted by the second Navigation 5 | series in the MAD Skills [videos](https://www.youtube.com/user/androiddevelopers) 6 | and [articles](https://medium.com/androiddevelopers). Specifically, episodes 7 | 1, 2, 3, and 4 walk through code from this sample. 8 | 9 | ### Features 10 | 11 | This sample showcases the following features of the Navigation component: 12 | 13 | * NavigationUI (episode 1) 14 | * Conditional Navigation (episode 2) 15 | * Nested Graphs and Include (episode 3) 16 | * Navigation in Feature Modules (episode 4) 17 | 18 | ### Screenshots 19 | Screenshot 20 | 21 | ### Other Resources 22 | 23 | * For an overview of using Navigation component, check out 24 | [Get started with the Navigation component](https://developer.android.com/guide/navigation/navigation-getting-started) 25 | * Consider including the [Navigation KTX libraries](https://developer.android.com/topic/libraries/architecture/adding-components#navigation) 26 | for more concise uses of the Navigation component. For example, calls to `Navigation.findNavController(view)` can 27 | be expressed as `view.findNavController()`. -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/androidTest/java/com/android/samples/donuttracker/OneTimeFlowTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker 17 | 18 | import androidx.fragment.app.testing.launchFragmentInContainer 19 | import androidx.navigation.Navigation 20 | import androidx.navigation.testing.TestNavHostController 21 | import androidx.test.core.app.ApplicationProvider 22 | import androidx.test.ext.junit.runners.AndroidJUnit4 23 | import com.android.samples.donuttracker.donut.DonutList 24 | import com.google.common.truth.Truth.assertThat 25 | import org.junit.Test 26 | import org.junit.runner.RunWith 27 | 28 | @RunWith(AndroidJUnit4::class) 29 | class OneTimeFlowTest { 30 | 31 | @Test 32 | fun testFirstRun() { 33 | val mockNavController = TestNavHostController(ApplicationProvider.getApplicationContext()) 34 | 35 | mockNavController.setGraph(R.navigation.nav_graph) 36 | 37 | val scenario = launchFragmentInContainer { 38 | DonutList().also { fragment -> 39 | fragment.viewLifecycleOwnerLiveData.observeForever{ viewLifecycleOwner -> 40 | if (viewLifecycleOwner != null){ 41 | Navigation.setViewNavController(fragment.requireView(), mockNavController) 42 | } 43 | } 44 | } 45 | } 46 | 47 | scenario.onFragment { 48 | assertThat(mockNavController.currentDestination?.id).isEqualTo(R.id.selectionFragment) 49 | } 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/coffee/CoffeeListViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.coffee 17 | 18 | import androidx.lifecycle.LiveData 19 | import androidx.lifecycle.ViewModel 20 | import androidx.lifecycle.viewModelScope 21 | import com.android.samples.donuttracker.model.Coffee 22 | import com.android.samples.donuttracker.storage.CoffeeDao 23 | import kotlinx.coroutines.Dispatchers 24 | import kotlinx.coroutines.launch 25 | 26 | /** 27 | * This ViewModel is used to access the underlying data and to observe changes to it. 28 | */ 29 | class CoffeeListViewModel(private val coffeeDao: CoffeeDao) : ViewModel() { 30 | 31 | // Users of this ViewModel will observe changes to its coffees list to know when 32 | // to redisplay those changes 33 | val coffeeList: LiveData> = coffeeDao.getAll() 34 | 35 | fun delete(coffee: Coffee) = viewModelScope.launch(Dispatchers.IO) { 36 | coffeeDao.delete(coffee) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/coffee/CoffeeViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.coffee 17 | 18 | import androidx.lifecycle.ViewModel 19 | import androidx.lifecycle.ViewModelProvider 20 | import com.android.samples.donuttracker.storage.CoffeeDao 21 | 22 | class CoffeeViewModelFactory(private val coffeeDao: CoffeeDao) : ViewModelProvider.Factory { 23 | 24 | override fun create(modelClass: Class): T { 25 | if (modelClass.isAssignableFrom(CoffeeListViewModel::class.java)) { 26 | @Suppress("UNCHECKED_CAST") 27 | return CoffeeListViewModel(coffeeDao) as T 28 | } else if (modelClass.isAssignableFrom(CoffeeEntryViewModel::class.java)) { 29 | @Suppress("UNCHECKED_CAST") 30 | return CoffeeEntryViewModel(coffeeDao) as T 31 | } 32 | throw IllegalArgumentException("Unknown ViewModel class") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/donut/DonutListViewModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.donut 17 | 18 | import androidx.lifecycle.LiveData 19 | import androidx.lifecycle.ViewModel 20 | import androidx.lifecycle.asLiveData 21 | import androidx.lifecycle.viewModelScope 22 | import com.android.samples.donuttracker.UserPreferencesRepository 23 | import com.android.samples.donuttracker.model.Donut 24 | import com.android.samples.donuttracker.storage.DonutDao 25 | import kotlinx.coroutines.Dispatchers 26 | import kotlinx.coroutines.launch 27 | 28 | /** 29 | * This ViewModel is used to access the underlying data and to observe changes to it. 30 | */ 31 | class DonutListViewModel( 32 | private val donutDao: DonutDao, 33 | private val userPreferencesRepository: UserPreferencesRepository 34 | ) : ViewModel() { 35 | 36 | // Users of this ViewModel will observe changes to its donuts list to know when 37 | // to redisplay those changes 38 | val donuts: LiveData> = donutDao.getAll() 39 | 40 | fun delete(donut: Donut) = viewModelScope.launch(Dispatchers.IO) { 41 | donutDao.delete(donut) 42 | } 43 | 44 | fun isFirstRun(): LiveData { 45 | return userPreferencesRepository.coffeeTrackerPreferencesFlow.asLiveData() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/donut/DonutViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.donut 17 | 18 | import androidx.lifecycle.ViewModel 19 | import androidx.lifecycle.ViewModelProvider 20 | import com.android.samples.donuttracker.UserPreferencesRepository 21 | import com.android.samples.donuttracker.storage.DonutDao 22 | 23 | class DonutViewModelFactory( 24 | private val donutDao: DonutDao, 25 | private val preferencesRepository: UserPreferencesRepository 26 | ) : ViewModelProvider.Factory { 27 | 28 | override fun create(modelClass: Class): T { 29 | if (modelClass.isAssignableFrom(DonutListViewModel::class.java)) { 30 | @Suppress("UNCHECKED_CAST") 31 | return DonutListViewModel(donutDao, preferencesRepository) as T 32 | } else if (modelClass.isAssignableFrom(DonutEntryViewModel::class.java)) { 33 | @Suppress("UNCHECKED_CAST") 34 | return DonutEntryViewModel(donutDao) as T 35 | } 36 | throw IllegalArgumentException("Unknown ViewModel class") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/model/Coffee.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.model 17 | 18 | import androidx.room.Entity 19 | import androidx.room.PrimaryKey 20 | 21 | /** 22 | * This class holds the data that we are tracking for each cup of coffee: its name, a description, 23 | * and a rating. 24 | */ 25 | @Entity 26 | data class Coffee( 27 | @PrimaryKey(autoGenerate = true) val id: Long, 28 | val name: String, 29 | val description: String = "", 30 | val rating: Int 31 | ) 32 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/model/Donut.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.model 17 | 18 | import androidx.room.Entity 19 | import androidx.room.PrimaryKey 20 | 21 | /** 22 | * This class holds the data that we are tracking for each donut: its name, a description, and 23 | * a rating. 24 | */ 25 | @Entity 26 | data class Donut( 27 | @PrimaryKey(autoGenerate = true) val id: Long, 28 | val name: String, 29 | val description: String = "", 30 | val rating: Int 31 | ) 32 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/storage/CoffeeDao.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.storage 17 | 18 | import androidx.lifecycle.LiveData 19 | import androidx.room.Dao 20 | import androidx.room.Delete 21 | import androidx.room.Insert 22 | import androidx.room.Query 23 | import androidx.room.Update 24 | import com.android.samples.donuttracker.model.Coffee 25 | 26 | @Dao 27 | interface CoffeeDao { 28 | @Query("SELECT * FROM coffee") 29 | fun getAll(): LiveData> 30 | 31 | @Query("SELECT * FROM coffee WHERE id = :id") 32 | suspend fun get(id: Long): Coffee 33 | 34 | @Insert 35 | suspend fun insert(coffee: Coffee): Long 36 | 37 | @Delete 38 | suspend fun delete(coffee: Coffee) 39 | 40 | @Update 41 | suspend fun update(coffee: Coffee) 42 | } 43 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/storage/DonutDao.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.storage 17 | 18 | import androidx.lifecycle.LiveData 19 | import androidx.room.Dao 20 | import androidx.room.Delete 21 | import androidx.room.Insert 22 | import androidx.room.Query 23 | import androidx.room.Update 24 | import com.android.samples.donuttracker.model.Donut 25 | 26 | /** 27 | * The Data Access Object used to retrieve and store data from/to the underlying database. 28 | * This API is not used directly; instead, callers should use the Repository which calls into 29 | * this DAO. 30 | */ 31 | @Dao 32 | interface DonutDao { 33 | @Query("SELECT * FROM donut") 34 | fun getAll(): LiveData> 35 | 36 | @Query("SELECT * FROM donut WHERE id = :id") 37 | suspend fun get(id: Long): Donut 38 | 39 | @Insert 40 | suspend fun insert(donut: Donut): Long 41 | 42 | @Delete 43 | suspend fun delete(donut: Donut) 44 | 45 | @Update 46 | suspend fun update(donut: Donut) 47 | } 48 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/java/com/android/samples/donuttracker/storage/SnackDatabase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 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 | package com.android.samples.donuttracker.storage 17 | 18 | import android.content.Context 19 | import androidx.room.Database 20 | import androidx.room.Room 21 | import androidx.room.RoomDatabase 22 | import com.android.samples.donuttracker.model.Coffee 23 | import com.android.samples.donuttracker.model.Donut 24 | 25 | /** 26 | * The underlying database where information about the donuts is stored. 27 | */ 28 | @Database(entities = arrayOf(Donut::class, Coffee::class), version = 1) 29 | abstract class SnackDatabase : RoomDatabase() { 30 | 31 | abstract fun donutDao(): DonutDao 32 | 33 | abstract fun coffeeDao(): CoffeeDao 34 | 35 | companion object { 36 | @Volatile private var INSTANCE: SnackDatabase? = null 37 | 38 | fun getDatabase(context: Context): SnackDatabase { 39 | val tempInstance = INSTANCE 40 | if (tempInstance != null) { 41 | return tempInstance 42 | } 43 | synchronized(this) { 44 | val instance = Room.databaseBuilder( 45 | context, 46 | SnackDatabase::class.java, 47 | "snack_database" 48 | ).build() 49 | INSTANCE = instance 50 | return instance 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/drawable/ic_clear_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 24 | 25 | 31 | 32 | 40 | 41 | 47 | 48 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/layout/coffee_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 23 | 24 | 29 | 30 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/layout/donut_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 23 | 24 | 29 | 30 | 39 | 40 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/menu/bottom_nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 26 | 27 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/menu/nav_drawer_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 27 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-developer-training/android-demos/bfcb54f1bb93008a5eb896e49112a8650eed9227/DonutTracker/ConditionalNavigation/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | #6200EE 19 | #3700B3 20 | #03DAC5 21 | #FBFBFB 22 | 23 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 16dp 19 | 20 | -------------------------------------------------------------------------------- /DonutTracker/ConditionalNavigation/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 27 | 28 | 32 | 33 | 27 | 28 | 32 | 33 | 27 | 28 | 32 | 33 | 27 | 28 | 32 | 33 |