Pro Yearly is on sale from $80 to $50! »

Navigation - Android Architecture Components

Navigation - Android Architecture Components

Introduction to Navigation components

6dd0483f1353a4a359e92633cfd65c64?s=128

Daichi Furiya (Wasabeef)

July 18, 2019
Tweet

Transcript

  1. Architecture Components ษڧձ ͋Μ͍͟Ώ͖ ͕͑Θ Θ͞ͼʔ; ͋Β͖ ୈ8ճ໨ Navigation

  2. Architecture Components ษڧձ ͱ͸ • Architecture Components ͷجૅ஌ࣝʹֶ͍ͭͯͿษڧձ • ओ࠵ɿGDG

    Tokyo ϋογϡλά: #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogle ࣾһͱ Google Developer Expert • ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ • ౰೔νϡʔλʔ : @95kugo, @STAR_ZERO, @tomoya0x00
  3. Architecture Components ษڧձ ͱ͸ • ܭ4ճͷ༧ఆ • ୈ5ճ: Lifecycle, ViewModel,

    LiveData ͷ෮श • ୈ6ճ: Room ͷ෮श, Paging • ୈ7ճ: WorkManager • ୈ8ճ: Navigation λΠϜςʔϒϧ 19:30ʙ19:35 ѫࡰˍઆ໌ 19:35ʙ20:15 આ໌ 20:15ʙ20:25 ٳܜ 20:25ʙ ՝୊औΓ૊Έ
  4. Architecture Components ͱ͸ ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •

    LiveData • ViewModel • Room • Paging • WorkManager • Navigation
  5. Architecture Components ͱ͸ ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •

    LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK ૊Έ߹Θͤར༻OK
  6. Architecture Components ͱ͸ ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •

    LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK ૊Έ߹Θͤར༻OK #1 #2 #3 #4
  7. Architecture Components ͱ͸ ෳ਺ͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •

    LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK ૊Έ߹Θͤར༻OK #1 #2 #3 #4 #5 #6 #7 #8
  8. Architecture Components ͷ໨త ݎ࿚ (robust) Ͱ ςετ͠΍͘͢ (testableʣ อक͠΍͍͢ (maintainable)

    ΞϓϦͷઃܭ͕Ͱ͖ΔΑ͏ʹखॿ͚͢Δ
  9. Navigation

  10. Navigation • Fragment Transaction ͷ؆қԽ • Ξχϝʔγϣϯ • σΟʔϓϦϯΫ •

    BottomNavigation / Toolbar ͳͲͱ؆୯ʹ࿈ܞ • Fragment ؒͰσʔλΛܕ҆શʹ౉ͤΔ • Navigation editor Λ࢖͏ͱ GUI Ͱ؆୯ʹઃఆ͕Ͱ͖Δ
  11. Navigation

  12. Gradle - dependencies dependencies { def nav_version = "2.1.0-alpha06" implementation

    “androidx.navigation:navigation-fragment-ktx:nav_version" implementation “androidx.navigation:navigation-ui-ktx:nav_version” }
  13. Gradle - dependencies buildscript { repositories { google() } dependencies

    { def nav_version = "2.1.0-alpha06" classpath “androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } } "// Kotlin apply plugin: "androidx.navigation.safeargs.kotlin"
  14. Basic • ͜͜Ͱ͸ɺ؆୯ͳ Navigation editor ͷ࢖͍ํ΍ཁૉͷઆ໌Λͯ͠ ͍͖·͢ɻ

  15. nav_graph.xml • res/navigation ͷ഑Լʹ Navigation ༻ ͷ xml Λ࡞Γɺ։͍ͯݟ͍ͯͩ͘͞ɻ
 ※

    ͜͜Ͱ͸ nav_graph.xml ͱ͠·͢
  16. nav_graph.xml Destinations panel

  17. nav_graph.xml Graph Editor

  18. nav_graph.xml Attributes

  19. nav_graph.xml GUI ্Ͱ֤ը໘Λ௥Ճ͢Δ৔߹ʹ͸ɺ ͜ͷϘλϯ͔Β؆୯ʹ௥ՃͰ͖·͢ɻ

  20. Demo: Navigation editor

  21. nav_graph.xml Ͱར༻͢Δओͳλά • <navigation /> : ϧʔτཁૉɻىಈޙͷ։࢝ҐஔͳͲΛࢦఆ • <fragment />

    : ֤ը໘ʢFragmentʣ • <action /> : ը໘ؒͷ֤ը໘ʢFragmentʣ • <argument /> : ը໘Ͱड͚औΔҾ਺ • <deeplink /> : σΟʔϓϦϯΫ • <dialog /> : DialogFragmentΛར༻͍ͯ͠Δ৔߹ͷը໘ • <include /> : Nested graphsɻάϥϑΛ෼ׂͯ͠੔ཧɾ࠶ར༻
  22. nav_graph.xml <?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/fragment_home">

    <fragment android:id="@+id/fragment_home" android:name="jp.wasabeef.navplayground.home.HomeFragment" tools:layout="@layout/fragment_home"> <action android:id="@+id/to_dashboard" app:destination="@id/fragment_dashboard""/> "</fragment> <fragment android:id="@+id/fragment_dashboard" android:name="jp.wasabeef.navplayground.dashboard.DashboardFragment" tools:layout="@layout/fragment_dashboard" > <argument android:name="id" app:argType="string" "/> "</fragment> "</navigation> ֤λάΛઆ໌͍͖ͯ͠·͢ɻ
  23. <navigation /> <?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"> "</navigation>

    ϧʔτཁૉʹͳΓ·͢ ͜ͷதʹ֤λάΛهࡌ͖ͯ͠·͢ɻ ޙड़͠·͕͢ɺىಈ࣌ͷॳظը໘ͷઃఆ΋͜͜ʹ͠·͢
  24. <fragment /> <?xml version="1.0" encoding="utf-8"?> <navigation ""... app:startDestination="@id/fragment_home"> <fragment android:id="@+id/fragment_home"

    android:name="jp.wasabeef.navplayground.home.HomeFragment" android:label="HomeFragment" tools:layout="@layout/fragment_home"> "</fragment> "</navigation> ͜ͷλάͰ͸ Fragment ͷ֘౰Ϋϥεͱࢦఆ͠·͢ ·ͨɺޙड़͠·͕͢ <action/>, < argument/>, <deeplink/> ͳͲ͸͜ͷ഑Լʹهࡌ͠·͢ɻ
  25. <?xml version="1.0" encoding="utf-8"?> <navigation ""... app:startDestination="@id/fragment_home"> <fragment android:id="@+id/fragment_home" android:name="jp.wasabeef.navplayground.home.HomeFragment" android:label="HomeFragment"

    tools:layout="@layout/fragment_home"> "</fragment> "</navigation> <fragment /> ͜ͷ HomeFragment Λىಈ࣌ͷॳظը໘ͱ͢Δ৔߹͸ <navigation/> ͷ startDestination ʹࢦఆ͠·͢
  26. <fragment /> GUI ্ͩͱɺ͜ͷҰͭʹ֘౰͠·͢ɻ

  27. <argument /> <?xml version="1.0" encoding="utf-8"?> <navigation ""...> <fragment android:id="@+id/fragment_dashboard" android:name="jp.wasabeef.navplayground.dashboard.DashboardFragment"

    android:label="DashboardFragment" tools:layout="@layout/fragment_dashboard" > <argument android:name="id" app:argType="string" "/> "</fragment> "</navigation> Ҿ਺ʹ͸ integer, float, long, boolean, string, reference, parcelable, serializable, enum ͷར༻͕Մೳ ར༻Ͱ͖Δܕɿhttps://developer.android.com/guide/navigation/navigation-pass-data#supported_argument_types
  28. <action /> <?xml version="1.0" encoding="utf-8"?> <navigation ""...> <fragment ""...> <action

    android:id="@+id/to_dashboard" app:destination="@id/fragment_dashboard""/> "</fragment> <fragment android:id=“@+id/fragment_dashboard" ""..."/> "</navigation> <action> ͰॏཁʹͳΔͷ͕ id ͱ destination Ͱ͢ɻ id ͸ setOnClickListener ͳͲͰࢦఆ͢Δͱ͖ʹ࢖ ͍ɺdestination ͸ભҠઌͷ Fragment Λࢦఆ͠·͢
  29. <action /> with anim ભҠ࣌ͷΞχϝʔγϣϯΛ௥Ճ͢Δ৔߹͸ɺ͜ͷΑ͏ʹͳΓ·͢ɻ <action android:id="@+id/to_dashboard" app:destination="@id/fragment_dashboard" app:enterAnim="@anim/nav_default_enter_anim" app:exitAnim="@anim/nav_default_exit_anim"

    app:popEnterAnim="@anim/nav_default_pop_enter_anim" app:popExitAnim="@anim/nav_default_pop_exit_anim" "/>
  30. <deeplink /> <fragment android:id="@+id/fragment_dashboard" android:name="jp.wasabeef.navplayground.dashboard.DashboardFragment" android:label="DashboardFragment" tools:layout="@layout/fragment_dashboard" > <argument android:name="id"

    app:argType="string" "/> <deeplink android:id="@+id/deeplink" app:uri="wasabeef.jp/dashboard/{id}" "/> "</fragment> σΟʔϓϦϯΫͰىಈ͍ͨ͠ Fragment ͷ഑Լ ʹىಈ͢Δ URIɺҾ਺ Λઃఆ͠·͢ɻ
  31. <deeplink /> - AndroidManifest.xml AndroidManifest ʹ <intent-filter/> Ͱ͸ͳ͘ <nav-graph/> Λ௥Ճ͢Δ͜ͱͰɺ͜͜ͷઃఆ

    ͸׬݁ͳΓ·͢ <?xml version="1.0" encoding="utf-8"?> <manifest ""...> <application ""...> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" "/> <category android:name="android.intent.category.LAUNCHER" "/> "</intent-filter> <nav-graph android:value="@navigation/nav_graph" "/> "</activity> "</application> "</manifest>
  32. <dialog /> <?xml version="1.0" encoding="utf-8"?> <navigation ""...> <fragment ""...> <action

    android:id="@+id/show_confirm" app:destination=“@id/fragment_confirm_dialog""/> "</fragment> <dialog android:id=“@+id/fragment_confirm_dialog” ""..."/> "</navigation> ࢖͍ํ͸ <fragment/> ͱಉ͡Ͱ DialogFragment Λ Navigation Ͱར༻͍ͨ͠৔߹͸ͪ͜ΒΛ࢖͍·͢ɻ
  33. NavHostFragment <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" "/> activity_main.xml

    ʹը໘੍ޚ͢Δ NavHostFragment Λઃఆ͠ɺ࡞੒ͨ͠ nav_graph.xml Λࢦఆ͢Δඞཁ͕͋Γ·͢ɻ
  34. Advanced • Nested navigation graph • BottomNavigation • FragmentNavigator

  35. Nested navigation graphs ͜ΕʹΑΓ͜Ε·Ͱ̍ͭͷ xml Ͱ ̍ͭͷ Activity ͕ભҠ͢Δ Fragment

    ͷઃఆ͕શͯ෼ׂɾ࠶ར༻Ͱ͖ΔΑ͏ʹͳΓ·͠ ͨɻ
  36. <?xml version="1.0" encoding="utf-8"?> <navigation""...> <include app:graph="@navigation/included_graph" ""... "</navigation> Nested navigation

    graphs ଞͷάϥϑΛ <include/> ͢Δ͜ͱ͕Ͱ͖·͢ɻ
  37. Z BottomNavigation "// MainActivity override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) "// ActionBarͷλΠτϧͳͲΛ੍ޚ setupActionBarWithNavController( navController, AppBarConfiguration( setOf( R.id.fragment_home, R.id.fragment_dashboard ) ) ) "// ભҠΛ੍ޚ nav_view.setupWithNavController(navController) } ͜Ε͚ͩͰ BottomNavigation ͱͷ࿈ܞՄೳ <!— activity_main.xml —> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_view" app:menu="@menu/bottom_nav_menu" ""..."/> <!— bottom_nav_menu.xml ※ nav_graph.xml ͷ <fragment "/>Ͱࢦఆ͢Δ Id ͱҰகͤ͞Δ —> <menu ""...> <item android:id="@+id/fragment_home" …"/> <item android:id=“@+id/fragment_dashboard" ""..."/> "</menu>
  38. FragmentNavigator nav_graph.xml ͰΧελϜλάΛ࡞ΕΔ Α͏ʹͳΓ·͢ɻ <fragment_with_anim android:id="@+id/fragment_home" android:name="jp.wasabeef.navplayground.home.HomeFragment" android:label="HomeFragment" tools:layout="@layout/fragment_home"> <action

    android:id="@+id/to_dashboard" app:destination="@id/fragment_dashboard" "/> "</fragment_with_anim>
  39. FragmentNavigator ͜ΕʹΑΓ͜Ε·Ͱ̍ͭͷ xml Ͱ ̍ͭͷ Activity ͕ભҠ͢Δ Fragment ͷઃఆ͕શͯ෼ׂɾ࠶ར༻Ͱ͖ΔΑ͏ʹͳΓ·͠ ͨɻ

    @Navigator.Name("fragment_with_anim") class DefaultNavigator( context: Context, manager: FragmentManager, containerId: Int ) : FragmentNavigator(context, manager, containerId) { override fun navigate( destination: Destination, args: Bundle?, navOptions: NavOptions?, navigatorExtras: Navigator.Extras? ): NavDestination? { return super.navigate(destination, args, exOp, navigatorExtras) } }
  40. FragmentNavigator MainActivity Ͱ ࡞੒ͨ͠ FragmentNavigator Λ NavController ʹ௥Ճ͠·͢ɻ ※ άϥϑ͕ઃఆ͞ΕΔલʹɺߦΘͳ͍ͱ͍͚·ͤΜɻ

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findNavController(R.id.nav_host_fragment).apply { navigatorProvider += DefaultNavigator( this@MainActivity, nav_host_fragment.childFragmentManager, R.id.nav_host_fragment ) setGraph(R.navigation.nav_graph) } }
  41. ՝୊

  42. ՝୊0 • ՝୊Ͱ࢖͏ίʔυͪ͜ΒͰ͢ɻ
 https://github.com/wasabeef/NavPlayground
 
 git clone git@github.com:wasabeef/NavPlayground.git
 
 


    Ϟδϡʔϧߏ੒
 app-step0 = ࡞ۀ༻Ϟδϡʔϧ
  43. ՝୊ • ՝୊1
 Navigation Խͯ͠ɺHome -> DashboardΛભҠͤ͞·͠ΐ͏ɻ
 ՝୊1.5 ભҠ࣌ͷΞχϝʔγϣϯΛ௥Ճͯ͠Έ·͠ΐ͏ɻ •

    ՝୊2
 <argument /> Λ࢖ͬͯ Dashboard ʹ id:String, name:String, location:String Λ౉ͯ͠Έ·͠ΐ͏ɻ • ՝୊3
 <deeplink /> Λ࢖ͬͯ Dashboard ͕͜ͷURLͰىಈͰ͖ΔΑ͏ʹ͠·͠ΐ͏ɻ
 https://sample.com/dashboard/{id}/{name}
 
 ىಈςετɿ
 adb shell am start -W -a android.intent.action.VIEW \
 -d "https://sample.com/dashboard/xxxxx/yyyyy"
  44. ՝୊ʢ͕࣌ؒ͋Ε͹ʣ • ՝୊4
 <include/> Λ࢖ͬͯάϥϑΛ෼ׂͯ͠Έ·͠ΐ͏ɻ
 • ՝୊5
 BottomNavigation ͷ࣮૷Λ Navigation

    Λ࢖ͬͯΈ·͠ΐ͏ɻ
  45. ౴͑ • ՝୊1 -> app-step1-action, app-step1-action-with-anim • ՝୊2 -> app-step2-args

    • ՝୊3 -> app-step3-deeplink • ՝୊4 -> app-step4-nested • ՝୊5 -> app-step5-bottom-nav • ՝୊6 -> app-step6-navigator
  46. ࢀߟࢿྉ • Android Navigation Architecture Component
 https://medium.com/@Alex.v/android-navigation-architecture- component-25b5a7aab8aa • Get

    started with the Navigation component
 https://developer.android.com/guide/navigation/navigation-getting- started •