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)
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
5
910
About Flutter Architecture
wasabeef
0
180
2023 Flutter/Dart Summary
wasabeef
0
46
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
150
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
2.8k
What it Takes to be a Flutter Developer
wasabeef
0
160
FlutterKaigi 2022 Keynote
wasabeef
1
560
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
Other Decks in Programming
See All in Programming
見えないメモリを観測する: PHP 8.4 `pg_result_memory_size()` とSQL結果のメモリ管理
kentaroutakeda
0
410
StarlingMonkeyを触ってみた話 - 2024冬
syumai
3
270
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
良いユニットテストを書こう
mototakatsu
8
2.8k
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
3
480
各クラウドサービスにおける.NETの対応と見解
ymd65536
0
110
From Translations to Multi Dimension Entities
alexanderschranz
2
130
fs2-io を試してたらバグを見つけて直した話
chencmd
0
240
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
110
創造的活動から切り拓く新たなキャリア 好きから始めてみる夜勤オペレーターからSREへの転身
yjszk
1
130
テストケースの名前はどうつけるべきか?
orgachem
PRO
0
140
20年もののレガシープロダクトに 0からPHPStanを入れるまで / phpcon2024
hirobe1999
0
500
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
Typedesign – Prime Four
hannesfritz
40
2.4k
Being A Developer After 40
akosma
87
590k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
347
20k
What's in a price? How to price your products and services
michaelherold
243
12k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.3k
Making Projects Easy
brettharned
116
5.9k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
28
4.4k
Fireside Chat
paigeccino
34
3.1k
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 •