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

Single Activity with MVVM

Avatar for TakuSemba TakuSemba
March 26, 2019

Single Activity with MVVM

Avatar for TakuSemba

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