* Navigation Component が、内部でどのような挙動をしているのか解説します * 挙動を理解した後に Navigation Component でできることや、制約について話します
View Slide
● 星川 貴樹 (@oboenikui)● エムスリー株式会社所属 (新卒3年目)● すき○ Android○ プロ野球観戦○ ネタTシャツお ぼ え に く い
● 会社で作っている新規アプリにNavigation Componentを導入しました● 機能紹介記事は多くありますが、動作に関する解説があまり多くなさそうだった & 動作を知らないためにモヤモヤしたことがありました● Navigation Componentがどのように動作しているかを理解したらスッキリ!
● Navigation Component が、内部でどのような挙動をしているのか解説します● 挙動を理解した後に Navigation Component でできることや、制約について話します
● 特に言及されてないところは 2.2.0-rc02 での情報です● 標準の機能(想定される使い方)として提供されていないという意味で「できない」という表現を使います● コードなどはスペースの都合上端折って書いているところがあります
● 画面遷移を、決まった原則に従って実装するためのライブラリ● 原則や実装方法などはここ1年で多くの方が解説してくださっているので割愛https://developer.android.com/guide/navigationhttps://droidkaigi.jp/2019/timetable/70415https://developer.android.com/guide/navigation/navigation-getting-started より引用
● 1つのActivityにおけるFragmentや他Activityへの遷移をXMLで定義する● 複雑なFragment遷移を良い感じにコントロールしてくれる● Navigation要素 (ToolbarやBottomNavigationなど) と連携して良い感じの遷移を簡単に記述できる
● なぜpopUpToオプションに のIDを指定する場合がある?● Fragmentをキャッシュできないの?● マルチモジュール構成のプロジェクトでのベストプラクティスは?● ……仕組みを先に理解しないとモヤモヤが残る
● XMLで定義したグラフ(木構造)● が内部ノード, が葉ノードになる○ これらのノードをNavDestinationと呼ぶ● は別扱い
● NavController#navigate メソッドでdestinationとして指定できるもの○ ただし は別物● を持つことが可能○ これらはNavDestinationのプロパティみたいなもの○ に関しては では使えない
app:startDestination="@+id/fragment_a1">app:startDestination="@id/fragment_b1">app:startDestination="@id/fragment_c">
Actionは遷移時のオプションをまとめたショートカットみたいなものActionを使わずに遷移もできるがここでは説明の簡略化のため割愛する
【見かけの挙動】 へのactionではStart Destinationへ更に遷移するここでは見かけ上 → という遷移
【本質的な話】 は親ノードである の子ノードだったら遷移可能。そのため → の遷移が可能親の子ノード親の子ノードではない者達親
【見かけの挙動】 から への遷移
親の子ノード親の子ノードではない者達親の子ノードではない者達親【本質的な話】 は親の親ノードである の子ノードだったら遷移可能。そのため → の遷移が可能
親の親の子ノード親親の親【本質的な話】 は親の親ノードである の子ノードだったら遷移可能。そのため → の遷移が可能親や親の親の子ノードではない者達親の子ノード
親親の子ノードではない者達親の子ノード【本質的な話】先祖ノードから辿れないノードへはActionでは直接遷移できない
親が知らない行き先
親が知らない行き先Deep Linkは遷移可能なノードをルートから全探索するので理論上どこへも遷移できるルート誰かこのDeep Link扱えない?
親が知らない行き先Deep Linkは遷移可能なノードをルートから全探索するので理論上どこへも遷移できるルート誰かこのDeep Link扱えない?無理 無理 わからん、聞いてみる わからん、聞いてみる
親が知らない行き先Deep Linkは遷移可能なノードをルートから全探索するので理論上どこへも遷移できるルート誰かこのDeep Link扱えない?無理 無理 無理 できるよ誰かこのDeep Link扱えない?
● XMLをパースしてNavGraphを構築したり、実際の遷移処理を行うクラス● NavControllerはFragmentManagerとは別に、遷移したNavDestinationをBack stackとして保持する
NavControllerのBack stackのイメージ
タグもスタックに積まれる
Activity遷移は管理する必要がないのでstackに積まない
積み残ったも同時に整理される
● popUpToで指定したdestinationがBack stackに積まれていた場合は、そこまでpopする機能● popUpToInclusive = true ならそのdestinationもpopするpopUpToInclusive = false ならその手前までpopする
popUpTo に を設定した場合ここまでのstackをpopする
popUpTo に を設定した場合
popUpTo に を設定した場合popUpTo にルートの を指定するのは、Back stackをクリアするのと同義
● 直下に を設定すると、どの子孫ノードからも実行できるActionが作られるapp:destination="@id/actv_a"/>よく解説ブログに出てくるAction
● 直下に を設定すると、どの子孫ノードからも実行できるActionが作られるandroid:id="@+id/action_actv_a"app:destination="@id/actv_a" />Global Action
Google I/Oでの発表によると、● 各モジュールごとにNavigation XMLを作る● メインモジュールのNavigation XMLでincludeするのが想定解の模様https://youtu.be/JFGq0asqSuA?t=1130
Google I/Oでの発表によると、● 各モジュールごとにNavigation XMLを作る● メインモジュールのNavigation XMLでincludeするのが想定解の模様https://youtu.be/JFGq0asqSuA?t=1130app:graph="@navigation/login_navigation"/>app:graph="@navigation/home_navigation"/>...
app:graph="@navigation/login_navigation" />app:graph="@navigation/home_navigation" />...
android:id="@+id/login_navigation" />android:id="@+id/home_navigation" />...
● 2.3.0から?使えるようになるみたいです● 現在SNAPSHOT版が公開されてますhttps://developer.android.com/guide/navigation/navigation-dynamic
● 例えば右のようなアプリでと遷移した後、バックボタンを押したらどう遷移するのが理想か● Navigationではスタック操作で可能な遷移のみ実現できるので以下のような遷移ができない
● BottomNavigationView などのナビゲーション用Viewで遷移する場合、Fragmentが新たに生成される○ Google Newsアプリが近い挙動● popBackStack しない限り生成済みのFragmentには戻らない、という挙動が徹底されている● ViewModelに表示に関する全てのデータを持たせ、Fragmentはそれに従って表示するだけ、というのを徹底する思想?
SafeArgs Pluginの問題だが、includeしたNavigation XML内で定義された を読んでくれない
app:destination="@+id/frag_sub"/>
// 理想: Stringを引数に取るメソッドが生成されてほしいMainNavigationDirections.actionMainToSub("hoge")
// 理想: Stringを引数に取るメソッドが生成されてほしいMainNavigationDirections.actionMainToSub("hoge")// 現実: 引数を何も取らないメソッドが生成されるMainNavigationDirections.actionMainToSub()
app:destination="@+id/frag_sub">
navigation-safe-args-generatorに実装があるので最新の実装はこちらから確認できますhttps://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/navigation/navigation-safe-args-generator/
● Navigation Component の動作について解説をした● Navigation Component の中の事情を知った上で、何ができるか/できないかについて解説した● Android Advent Calendar にも関連記事を書く予定● 実験用に作ったサンプルリポジトリはこちら(最新版をpushし忘れたので後で確認してください^^;)https://github.com/oboenikui/navigation-experiment
android:id="@+id/navigation_a"app:startDestination="@+id/fragment_a1">
android:id="@+id/navigation_b"app:startDestination="@+id/fragment_b1">
android:id="@+id/navigation_c"app:startDestination="@+id/fragment_c">