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
9k
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)
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
5
1.9k
About Flutter Architecture
wasabeef
1
240
2023 Flutter/Dart Summary
wasabeef
0
73
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
180
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3k
What it Takes to be a Flutter Developer
wasabeef
0
200
FlutterKaigi 2022 Keynote
wasabeef
1
600
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.4k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.2k
Other Decks in Programming
See All in Programming
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
210
Team operations that are not burdened by SRE
kazatohiei
1
270
PHPでWebSocketサーバーを実装しよう2025
kubotak
0
230
Systèmes distribués, pour le meilleur et pour le pire - BreizhCamp 2025 - Conférence
slecache
0
110
Azure AI Foundryではじめてのマルチエージェントワークフロー
seosoft
0
140
「Cursor/Devin全社導入の理想と現実」のその後
saitoryc
0
580
A2A プロトコルを試してみる
azukiazusa1
2
1.2k
deno-redisの紹介とJSRパッケージの運用について (toranoana.deno #21)
uki00a
0
150
Select API from Kotlin Coroutine
jmatsu
1
190
都市をデータで見るってこういうこと PLATEAU属性情報入門
nokonoko1203
1
580
Java on Azure で LangGraph!
kohei3110
0
170
AIコーディング道場勉強会#2 君(エンジニア)たちはどう生きるか
misakiotb
1
260
Featured
See All Featured
Facilitating Awesome Meetings
lara
54
6.4k
The World Runs on Bad Software
bkeepers
PRO
69
11k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Embracing the Ebb and Flow
colly
86
4.7k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Making the Leap to Tech Lead
cromwellryan
134
9.4k
4 Signs Your Business is Dying
shpigford
184
22k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
680
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
138
34k
Build The Right Thing And Hit Your Dates
maggiecrowley
36
2.8k
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 git@github.com: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 •