Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Single Activity with MVVM

TakuSemba
March 26, 2019

Single Activity with MVVM

TakuSemba

March 26, 2019
Tweet

More Decks by TakuSemba

Other Decks in Technology

Transcript

  1. <?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph"> <fragment android:id="@+id/firstFragment"

    android:name=“your.package.FirstFragment” /> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment”/> </navigation> <navigation <fragment android:id="@+id/firstFragment" android:name=“your.package.FirstFragment" /> <fragment android:id="@+id/secondFragment" android:name="your.package.SecondFragment"/> </navigation>
  2. <?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment"> <fragment

    android:id="@+id/firstFragment" android:name=“your.package.FirstFragment” /> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment”/> </navigation> <navigation app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name=“your.package.FirstFragment" /> <fragment android:id="@+id/secondFragment" android:name="your.package.SecondFragment"/> </navigation>
  3. <?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment"> <fragment

    android:id="@+id/firstFragment" android:name=“your.package.FirstFragment"> <action android:id="@+id/to_secondFragment" app:destination="@id/secondFragment"/> </fragment> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment"/> </navigation> <fragment android:id="@+id/firstFragment" android:name="your.package.FirstFragment"> <action android:id="@+id/to_secondFragment" app:destination="@id/secondFragment"/> </fragment>
  4. <?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment"> <fragment

    android:id="@+id/firstFragment" android:name="your.package.FirstFragment"> <action android:id="@+id/to_secondFragment" app:destination="@id/secondFragment"/> </fragment> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment"> <argument android:name="userId" app:argType="string"/> </fragment> </navigation> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment"> <argument android:name="userId" app:argType="string"/> </fragment>
  5. <?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" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment"> <fragment

    android:id="@+id/firstFragment" android:name="your.package.FirstFragment"> <action android:id="@+id/to_secondFragment" app:destination="@id/secondFragment"/> </fragment> <fragment android:id="@+id/secondFragment" android:name=“your.package.SecondFragment"> <argument android:name="userId" app:argType="string"/> </fragment> </navigation>
  6. val navController = findNavController(R.id.host_fragment) // find from activity val navController

    = findNavController() // find from fragment val navController = findNavController() // find from view
  7. val navController = findNavController(R.id.host_fragment) // find from activity val navController

    = findNavController() // find from fragment val navController = findNavController() // find from view val args = bundleOf(SecondFragment.KEY_USER_ID to userId) navController.navigate(R.id.toSecondFragment, args) // navigate to secondFragment.kt
  8. val navController = findNavController(R.id.host_fragment) // find from activity val navController

    = findNavController() // find from fragment val navController = findNavController() // find from view // navigate to secondFragment.kt val directions = FirstFragmentDirections.toSecondFragment(userId) navController.navigate(directions)
  9. val navController = findNavController(R.id.host_fragment) // find from activity val navController

    = findNavController() // find from fragment val navController = findNavController() // find from view // navigate to secondFragment.kt val directions = FirstFragmentDirections.toSecondFragment(userId) navController.navigate(directions) // get userId from arguments val args = SecondFragmentArgs.fromBundle(requireArguments()) val userId = args.userId
  10. val navController = findNavController(R.id.host_fragment) // find from activity val navController

    = findNavController() // find from fragment val navController = findNavController() // find from view // navigate to secondFragment.kt val directions = FirstFragmentDirections.toSecondFragment(userId) navController.navigate(directions) // get userId from arguments private val args by navArgs<SecondFragmentArgs>() val userId = args.userId
  11. <?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" app:startDestination="@id/launcherFragment" > <action

    android:id="@+id/action_global_ maintainanceFragment” app:destination="@id/maintainanceFragment" /> <fragment … /> <fragment … /> </navigation> // global action
  12. Nav Options special options for navigate actions public NavOptions.Builder setPopUpTo

    (int destinationId, boolean inclusive) public NavOptions.Builder setLaunchSingleTop (boolean singleTop) …
  13. val directions = SplashDirections.showLoginFragment() val options = NavOptions.Builder() .setPopUpTo(R.id.splashFragment, true)

    .build() navController.navigate(directions, options) // navigate with stacked fragmetns popoed up
  14. // navigate to loginFragment val directions = SplashDirections.showLoginFragment() navController.navigate(directions) <?xml

    version="1.0" encoding="utf-8"?> <navigation> <fragment android:id="@+id/splashFragment" android:name="your.package.SplashFragment" tools:layout="@layout/fragment_splash"> <action android:id="@+id/showLoginFragment" app:destination="@id/loginFragment" app:popUpTo="@id/splashFragment" app:popUpToInclusive="true"/> </fragment> </navigation> <action app:popUpTo="@id/splashFragment" app:popUpToInclusive="true"/> // navigate with stacked fragmetns popoed up
  15. // navigate as single-top val directions = NavGraphDirections.showBarFragment() navController.navigate(directions) val

    directionsAgain = NavGraphDirections.showBarFragment() navController.navigate(directionsAgain)
  16. val directions = NavGraphDirections.showBarFragment() navController.navigate(directions) val directionsAgain = NavGraphDirections.showBarFragment() val

    options = NavOptions.Builder() .setLaunchSingleTop(true) .build() navController.navigate(directions, options) // navigate as single-top
  17. // navigate to barFragment val directions = NavGraphDirections.showBarFragment() navController.navigate(directions) <?xml

    version="1.0" encoding="utf-8"?> <navigation> <fragment android:id="@+id/splashFragment" android:name="your.package.SplashFragment" tools:layout="@layout/fragment_splash"> <action android:id="@+id/showLoginFragment" app:destination="@id/loginFragment" app:launchSingleTop="true"/> </fragment> </navigation> <action app:launchSingleTop="true"/> // navigate as single-top
  18. navController.popBackStack() // navigate back // observe data override fun onViewCreated(view:

    View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.user.observe(this) { user -> textView.text = user.name } }
  19. navController.popBackStack() // navigate back // observe data override fun onViewCreated(view:

    View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.user.observe(this) { user -> textView.text = user.name } } observe(this) { user -> }
  20. navController.popBackStack() // navigate back // observe data override fun onViewCreated(view:

    View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.user.observe(this) { user -> textView.text = user.name } } observe(this) { user -> } override fun onDestroy() { super.onDestroy() // not called yet }
  21. navController.popBackStack() // navigate back // observe data override fun onViewCreated(view:

    View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.user.observe(viewLifecycleOwner) { user -> textView.text = user.name } } override fun onDestroy() { super.onDestroy() // not called yet } observe(viewLifecycleOwner) { user -> }
  22. navController.popBackStack() // navigate back // observe data override fun onViewCreated(view:

    View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.user.observe(viewLifecycleOwner) { user -> textView.text = user.name } } override fun onDestroyView() { super.onDestroyView() // observer is removed. } observe(viewLifecycleOwner) { user -> }
  23. class FooViewModel : ViewModel() { val snackbarMessage: LiveData<SnackbarMessage> = MutableLiveData()

    } // viewModel // observe data override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.snackbarMessage.observe(viewLifecycleOwner) { message -> // show snackbar } }
  24. class FooViewModel : ViewModel() { val snackbarMessage: LiveData<Event<SnackbarMessage>> = MutableLiveData()

    } // viewModel // observe data override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.snackbarMessage.observe(viewLifecycleOwner) { message -> // show snackbar } }
  25. class FooViewModel : ViewModel() { val snackbarMessage: LiveData<Event<SnackbarMessage>> = MutableLiveData()

    } // viewModel // observe data override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.snackbarMessage.observe(viewLifecycleOwner) { message -> // show snackbar } } // Event.kt from https://github.com/google/iosched LiveData<Event<SnackbarMessage>>
  26. class FooViewModel : ViewModel() { // Event.kt from https://github.com/google/iosched val

    snackbarMessage: LiveData<Event<SnackbarMessage>> = MutableLiveData() } // viewModel // observe data override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel.snackbarMessage.observe(viewLifecycleOwner) { event -> event.getContentIfNotHandled()?.let { message -> // show snackbar } } }
  27. // scope for viewModel private val activityScopedViewModel: FooViewModel by activityViewModels

    { viewModelFactory } private val fragmentScopedViewModel: BarViewModel by viewModels { viewModelFactory } Activity Scope ≒ App Scope
  28. // scope for viewModel private val activityScopedViewModel: FooViewModel by activityViewModels

    { viewModelFactory } private val fragmentScopedViewModel: BarViewModel by viewModels { viewModelFactory } Activity Scope ≒ App Scope … Fragment Scope Fragment Scope