Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Navigation Componentで先に知っておきたかったポイント

Navigation Componentで先に知っておきたかったポイント

* Navigation Component が、内部でどのような挙動をしているのか解説します
* 挙動を理解した後に Navigation Component でできることや、制約について話します

Takaki Hoshikawa

November 21, 2019
Tweet

More Decks by Takaki Hoshikawa

Other Decks in Programming

Transcript

  1. View Slide

  2. ● 星川 貴樹 (@oboenikui)
    ● エムスリー株式会社所属 (新卒3年目)
    ● すき
    ○ Android
    ○ プロ野球観戦
    ○ ネタTシャツ
    お ぼ え に く い

    View Slide

  3. ● 会社で作っている新規アプリにNavigation Componentを導入しま
    した
    ● 機能紹介記事は多くありますが、動作に関する解説があまり多くなさ
    そうだった & 動作を知らないためにモヤモヤしたことがありました
    ● Navigation Componentがどのように動作しているかを理解したら
    スッキリ!

    View Slide

  4. ● Navigation Component が、内部でどのような挙動をしているの
    か解説します
    ● 挙動を理解した後に Navigation Component でできることや、
    制約について話します

    View Slide

  5. ● 特に言及されてないところは 2.2.0-rc02 での情報です
    ● 標準の機能(想定される使い方)として提供されていないという意味
    で「できない」という表現を使います
    ● コードなどはスペースの都合上端折って書いているところがあります

    View Slide

  6. View Slide

  7. ● 画面遷移を、決まった原則に従っ
    て実装するためのライブラリ
    ● 原則や実装方法などはここ1年で多
    くの方が解説してくださっている
    ので割愛
    https://developer.android.com/guide/navigation
    https://droidkaigi.jp/2019/timetable/70415
    https://developer.android.com/guide/navigation
    /navigation-getting-started より引用

    View Slide

  8. ● 1つのActivityにおけるFragmentや他Activityへの遷移をXMLで
    定義する
    ● 複雑なFragment遷移を良い感じにコントロールしてくれる
    ● Navigation要素 (ToolbarやBottomNavigationなど) と連携
    して良い感じの遷移を簡単に記述できる

    View Slide

  9. ● なぜpopUpToオプションに のIDを指定する場合が
    ある?
    ● Fragmentをキャッシュできないの?
    ● マルチモジュール構成のプロジェクトでのベストプラクティスは?
    ● ……
    仕組みを先に理解しないとモヤモヤが残る

    View Slide

  10. View Slide

  11. ● XMLで定義したグラフ(木構造)
    ● が内部ノード,
    が葉ノードになる
    ○ これらのノードをNavDestinationと呼ぶ
    ● は別扱い

    View Slide

  12. ● NavController#navigate メソッドでdestinationとして指定
    できるもの
    ○ ただし は別物
    ● を持つことが可能
    ○ これらはNavDestinationのプロパティみたいなもの
    ○ に関しては では使えない

    View Slide

  13. app:startDestination="@+id/fragment_a1">


    app:startDestination="@id/fragment_b1">



    app:startDestination="@id/fragment_c">




    View Slide

  14. View Slide

  15. Actionは遷移時のオプションをまと
    めたショートカットみたいなもの
    Actionを使わずに遷移もできるがこ
    こでは説明の簡略化のため割愛する

    View Slide

  16. 【見かけの挙動】
    へのactionでは
    Start Destinationへ更に遷移する
    ここでは見かけ上

    という遷移

    View Slide

  17. 【本質的な話】
    は親ノードである
    の子ノードだったら
    遷移可能。そのため

    の遷移が可能
    親の子ノード
    親の子ノード
    ではない者達

    View Slide

  18. View Slide

  19. 【見かけの挙動】
    から
    への遷移

    View Slide

  20. 親の子ノード
    親の子ノードではない者達
    親の子ノード
    ではない者達

    【本質的な話】
    は親の親ノードであ
    る の子ノードだっ
    たら遷移可能。そのため

    の遷移が可能

    View Slide

  21. 親の親の
    子ノード

    親の親
    【本質的な話】
    は親の親ノードであ
    る の子ノードだっ
    たら遷移可能。そのため

    の遷移が可能
    親や親の親の子ノードではない者達
    親の子ノード

    View Slide

  22. View Slide


  23. 親の子ノード
    ではない者達
    親の子ノード
    【本質的な話】
    先祖ノードから辿れないノードへは
    Actionでは直接遷移できない

    View Slide

  24. 親が知らない
    行き先

    View Slide

  25. 親が知らない
    行き先
    Deep Linkは遷移可能なノードを
    ルートから全探索するので理論上
    どこへも遷移できる
    ルート
    誰かこのDeep Link扱えない?

    View Slide

  26. 親が知らない
    行き先
    Deep Linkは遷移可能なノードを
    ルートから全探索するので理論上
    どこへも遷移できる
    ルート
    誰かこのDeep Link扱えない?
    無理 無理 わからん、聞いてみる わからん、聞いてみる

    View Slide

  27. 親が知らない
    行き先
    Deep Linkは遷移可能なノードを
    ルートから全探索するので理論上
    どこへも遷移できる
    ルート
    誰かこのDeep Link扱えない?
    無理 無理 無理 できるよ
    誰かこのDeep Link扱えない?

    View Slide

  28. ● XMLをパースしてNavGraphを構築したり、実際の遷移処理を行うク
    ラス
    ● NavControllerはFragmentManagerとは別に、遷移した
    NavDestinationをBack stackとして保持する

    View Slide

  29. NavControllerの
    Back stackのイメージ

    View Slide

  30. タグも
    スタックに積まれる

    View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. View Slide

  41. View Slide

  42. View Slide

  43. Activity遷移は管理する必要
    がないのでstackに積まない

    View Slide

  44. View Slide

  45. 積み残ったも
    同時に整理される

    View Slide

  46. ● popUpToで指定したdestinationがBack stackに積まれていた場
    合は、そこまでpopする機能
    ● popUpToInclusive = true ならそのdestinationもpopする
    popUpToInclusive = false ならその手前までpopする

    View Slide

  47. popUpTo に を設定した場合
    ここまでの
    stackを
    popする

    View Slide

  48. popUpTo に を設定した場合

    View Slide

  49. popUpTo に を設定した場合

    View Slide

  50. popUpTo に を設定した場合
    popUpTo にルートの を指定
    するのは、Back stackをクリアするのと同義

    View Slide

  51. View Slide

  52. ● 直下に を設定すると、どの子孫ノードからも
    実行できるActionが作られる



    app:destination="@id/actv_a"/>




    よく解説ブログに出てくる
    Action

    View Slide

  53. ● 直下に を設定すると、どの子孫ノードからも
    実行できるActionが作られる





    android:id="@+id/action_actv_a"
    app:destination="@id/actv_a" />

    Global Action

    View Slide

  54. Google I/Oでの発表によると、
    ● 各モジュールごとにNavigation XML
    を作る
    ● メインモジュールのNavigation XML
    でincludeする
    のが想定解の模様
    https://youtu.be/JFGq0asqSuA?t=1130

    View Slide

  55. Google I/Oでの発表によると、
    ● 各モジュールごとにNavigation XML
    を作る
    ● メインモジュールのNavigation XML
    でincludeする
    のが想定解の模様
    https://youtu.be/JFGq0asqSuA?t=1130


    app:graph="@navigation/login_navigation"
    />
    app:graph="@navigation/home_navigation"
    />
    ...

    View Slide



  56. app:graph="@navigation/login_navigation" />
    app:graph="@navigation/home_navigation" />
    ...

    View Slide



  57. android:id="@+id/login_navigation" />
    android:id="@+id/home_navigation" />
    ...

    View Slide

  58. ● 2.3.0から?使えるようになるみたいです
    ● 現在SNAPSHOT版が公開されてます
    https://developer.android.com/guide/navigation/navigation-dynamic

    View Slide

  59. View Slide

  60. ● 例えば右のようなアプリで
    と遷移した後、バックボタンを押したらどう遷移
    するのが理想か
    ● Navigationではスタック操作で可能な遷移のみ
    実現できるので以下のような遷移ができない

    View Slide

  61. ● BottomNavigationView などのナビゲーション用Viewで遷移する
    場合、Fragmentが新たに生成される
    ○ Google Newsアプリが近い挙動
    ● popBackStack しない限り生成済みのFragmentには戻らない、と
    いう挙動が徹底されている
    ● ViewModelに表示に関する全てのデータを持たせ、Fragmentはそ
    れに従って表示するだけ、というのを徹底する思想?

    View Slide

  62. SafeArgs Pluginの問題だが、includeしたNavigation XML内で定
    義された を読んでくれない

    View Slide




  63. app:destination="@+id/frag_sub"/>







    View Slide

  64. // 理想: Stringを引数に取るメソッドが生成されてほしい
    MainNavigationDirections.actionMainToSub("hoge")

    View Slide

  65. // 理想: Stringを引数に取るメソッドが生成されてほしい
    MainNavigationDirections.actionMainToSub("hoge")
    // 現実: 引数を何も取らないメソッドが生成される
    MainNavigationDirections.actionMainToSub()

    View Slide




  66. app:destination="@+id/frag_sub">









    View Slide

  67. navigation-safe-args-generatorに実装があるので最新の実装は
    こちらから確認できます
    https://android.googlesource.com/platform/frameworks/support/+/androidx-m
    aster-dev/navigation/navigation-safe-args-generator/

    View Slide

  68. ● Navigation Component の動作について解説をした
    ● Navigation Component の中の事情を知った上で、
    何ができるか/できないかについて解説した
    ● Android Advent Calendar にも関連記事を書く予定
    ● 実験用に作ったサンプルリポジトリはこちら
    (最新版をpushし忘れたので後で確認してください^^;)
    https://github.com/oboenikui/navigation-experiment

    View Slide

  69. android:id="@+id/navigation_a"
    app:startDestination="@+id/fragment_a1">





    View Slide

  70. android:id="@+id/navigation_a"
    app:startDestination="@+id/fragment_a1">





    View Slide




  71. android:id="@+id/navigation_b"
    app:startDestination="@+id/fragment_b1">





    View Slide

  72. android:id="@+id/navigation_a"
    app:startDestination="@+id/fragment_a1">





    View Slide





  73. android:id="@+id/navigation_c"
    app:startDestination="@+id/fragment_c">




    View Slide