Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Navigation - Android Architecture Components
Search
Daichi Furiya (Wasabeef)
July 18, 2019
Programming
6
8.7k
Navigation - Android Architecture Components
Introduction to Navigation components
Daichi Furiya (Wasabeef)
July 18, 2019
Tweet
Share
More Decks by Daichi Furiya (Wasabeef)
See All by Daichi Furiya (Wasabeef)
About Flutter Architecture
wasabeef
0
160
2023 Flutter/Dart Summary
wasabeef
0
45
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
140
I/O Extended 2023 - Flutter 活用事例
wasabeef
11
2.8k
What it Takes to be a Flutter Developer
wasabeef
0
160
FlutterKaigi 2022 Keynote
wasabeef
1
550
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.3k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.1k
Flutter Hooks, sometimes Jetpack Compose
wasabeef
3
1.8k
Other Decks in Programming
See All in Programming
初めてDefinitelyTypedにPRを出した話
syumai
0
420
cmp.Or に感動した
otakakot
3
200
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
tasshi
2
350
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
2k
Remix on Hono on Cloudflare Workers
yusukebe
1
300
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
190
Jakarta EE meets AI
ivargrimstad
0
110
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
1
100
What’s New in Compose Multiplatform - A Live Tour (droidcon London 2024)
zsmb
1
480
Enabling DevOps and Team Topologies Through Architecture: Architecting for Fast Flow
cer
PRO
0
340
Realtime API 入門
riofujimon
0
150
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
Featured
See All Featured
Building a Scalable Design System with Sketch
lauravandoore
459
33k
Building Your Own Lightsaber
phodgson
103
6.1k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
65k
RailsConf 2023
tenderlove
29
900
Six Lessons from altMBA
skipperchong
27
3.5k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.3k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
24k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.8k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Being A Developer After 40
akosma
87
590k
Transcript
Architecture Components ษڧձ ͋Μ͍͟Ώ͖ ͕͑Θ Θ͞ͼʔ; ͋Β͖ ୈ8ճ Navigation
Architecture Components ษڧձ ͱ • Architecture Components ͷجૅࣝʹֶ͍ͭͯͿษڧձ • ओ࠵ɿGDG
Tokyo ϋογϡλά: #gdgtokyo • ߨࢣɺνϡʔλʔɿGoogle ࣾһͱ Google Developer Expert • ʢ͋Μ͍͟Ώ͖ɺ ͕͑ΘɺΘ͞ͼʔ;ɺ͋Β͖ʣ • νϡʔλʔ : @95kugo, @STAR_ZERO, @tomoya0x00
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ʙ ՝औΓΈ
Architecture Components ͱ ෳͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •
LiveData • ViewModel • Room • Paging • WorkManager • Navigation
Architecture Components ͱ ෳͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •
LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK Έ߹Θͤར༻OK
Architecture Components ͱ ෳͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •
LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK Έ߹Θͤར༻OK #1 #2 #3 #4
Architecture Components ͱ ෳͷػೳɾϥΠϒϥϦͷ૯শ • Data Binding • Lifecycles •
LiveData • ViewModel • Room • Paging • WorkManager • Navigation ݸผར༻OK Έ߹Θͤར༻OK #1 #2 #3 #4 #5 #6 #7 #8
Architecture Components ͷత ݎ࿚ (robust) Ͱ ςετ͘͢͠ (testableʣ อक͍͢͠ (maintainable)
ΞϓϦͷઃܭ͕Ͱ͖ΔΑ͏ʹखॿ͚͢Δ
Navigation
Navigation • Fragment Transaction ͷ؆қԽ • Ξχϝʔγϣϯ • σΟʔϓϦϯΫ •
BottomNavigation / Toolbar ͳͲͱ؆୯ʹ࿈ܞ • Fragment ؒͰσʔλΛܕ҆શʹͤΔ • Navigation editor Λ͏ͱ GUI Ͱ؆୯ʹઃఆ͕Ͱ͖Δ
Navigation
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” }
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"
Basic • ͜͜Ͱɺ؆୯ͳ Navigation editor ͷ͍ํཁૉͷઆ໌Λͯ͠ ͍͖·͢ɻ
nav_graph.xml • res/navigation ͷԼʹ Navigation ༻ ͷ xml Λ࡞Γɺ։͍ͯݟ͍ͯͩ͘͞ɻ ※
͜͜Ͱ nav_graph.xml ͱ͠·͢
nav_graph.xml Destinations panel
nav_graph.xml Graph Editor
nav_graph.xml Attributes
nav_graph.xml GUI ্Ͱ֤ը໘ΛՃ͢Δ߹ʹɺ ͜ͷϘλϯ͔Β؆୯ʹՃͰ͖·͢ɻ
Demo: Navigation editor
nav_graph.xml Ͱར༻͢Δओͳλά • <navigation /> : ϧʔτཁૉɻىಈޙͷ։࢝ҐஔͳͲΛࢦఆ • <fragment />
: ֤ը໘ʢFragmentʣ • <action /> : ը໘ؒͷ֤ը໘ʢFragmentʣ • <argument /> : ը໘Ͱड͚औΔҾ • <deeplink /> : σΟʔϓϦϯΫ • <dialog /> : DialogFragmentΛར༻͍ͯ͠Δ߹ͷը໘ • <include /> : Nested graphsɻάϥϑΛׂͯ͠ཧɾ࠶ར༻
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> ֤λάΛઆ໌͍͖ͯ͠·͢ɻ
<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>
ϧʔτཁૉʹͳΓ·͢ ͜ͷதʹ֤λάΛهࡌ͖ͯ͠·͢ɻ ޙड़͠·͕͢ɺىಈ࣌ͷॳظը໘ͷઃఆ͜͜ʹ͠·͢
<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/> ͳͲ͜ͷԼʹهࡌ͠·͢ɻ
<?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 ʹࢦఆ͠·͢
<fragment /> GUI ্ͩͱɺ͜ͷҰͭʹ֘͠·͢ɻ
<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
<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 Λࢦఆ͠·͢
<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" "/>
<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ɺҾ Λઃఆ͠·͢ɻ
<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>
<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 Ͱར༻͍ͨ͠߹ͪ͜ΒΛ͍·͢ɻ
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 Λࢦఆ͢Δඞཁ͕͋Γ·͢ɻ
Advanced • Nested navigation graph • BottomNavigation • FragmentNavigator
Nested navigation graphs ͜ΕʹΑΓ͜Ε·Ͱ̍ͭͷ xml Ͱ ̍ͭͷ Activity ͕ભҠ͢Δ Fragment
ͷઃఆ͕શׂͯɾ࠶ར༻Ͱ͖ΔΑ͏ʹͳΓ·͠ ͨɻ
<?xml version="1.0" encoding="utf-8"?> <navigation""...> <include app:graph="@navigation/included_graph" ""... "</navigation> Nested navigation
graphs ଞͷάϥϑΛ <include/> ͢Δ͜ͱ͕Ͱ͖·͢ɻ
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>
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>
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) } }
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) } }
՝
՝0 • ՝Ͱ͏ίʔυͪ͜ΒͰ͢ɻ https://github.com/wasabeef/NavPlayground git clone
[email protected]
:wasabeef/NavPlayground.git
Ϟδϡʔϧߏ app-step0 = ࡞ۀ༻Ϟδϡʔϧ
՝ • ՝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"
՝ʢ͕࣌ؒ͋Εʣ • ՝4 <include/> ΛͬͯάϥϑΛׂͯ͠Έ·͠ΐ͏ɻ • ՝5 BottomNavigation ͷ࣮Λ Navigation
ΛͬͯΈ·͠ΐ͏ɻ
͑ • ՝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
ࢀߟࢿྉ • 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 •