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

詳解 RelativeLayoutの内部実装

HiroYUKI Seto
February 03, 2018

詳解 RelativeLayoutの内部実装

2018/2/9
DroidKaigi 2018 DAY02 room1 10:30~
発表の付録1

HiroYUKI Seto

February 03, 2018
Tweet

More Decks by HiroYUKI Seto

Other Decks in Technology

Transcript

  1. DroidKaigi 2018付録1
    詳解
    RelativeLayoutの
    内部実装
    株式会社ノハナ 瀬戸優之
    @seto_hi

    View Slide

  2. RelativeLayoutのポイント
    =Graph

    View Slide

  3. Graph
    グラフ(英: Graph)とは、
    ノード(頂点)群とノード間の連結関係を表す
    エッジ(枝)群で構成される抽象データ型、
    and・orその実装である具象データ型である。
    (wikipedia)

    View Slide

  4. DependencyGraph
    ● 有向グラフ
    ● mNodes = 子Viewすべて、ArrayList
    ● mKeyNodes = IDを持つ子View、SparseArray
    Node
    ● dependents = 参照しているNode
    ● dependencies = 参照されているNode

    View Slide

  5. RelativeLayout#onMeasure

    View Slide

  6. RelativeLayout#onMeasure
    1. DependencyGraphを作る
    2. 横方向でGraphのrootからmeasure、仮レイアウト
    3. 縦方向でGraphのrootからmeasure、仮レイアウト
    ○ 自身のサイズも仮決定

    View Slide

  7. RelativeLayout#onMeasure
    4. 自身がwrap_contentなら
    ○ 子のサイズとMeasureSpecから自身のサイズを修正
    ○ 中央寄せのViewの位置を修正
    5. Gravityによって位置を本決め
    6. setMeasuredDimensions

    View Slide

  8. mesureでの仮レイアウト
    ● 参照のGraphのrootからmeasure + 仮レイアウトしていく
    ● measure対象のViewが参照しているViewは
    必ず仮レイアウト済み
    ● measureさえすればmeasure対象のViewの
    仮レイアウト位置が確定できる

    View Slide

  9. 子ViewのmeasureSpec
    1. 左右(or上下)ともに参照しているViewがある
    ○ 左右(or上下)のViewの間のサイズ + EXACTLY
    2. 1.でない場合
    ○ 子Viewがサイズ決め打ち
    ■ 子Viewのサイズと余りサイズの最小値 + EXACTLY
    ○ 子Viewがmatch_parent
    ■ RelativeLayoutの余りサイズ + EXACTLY※
    ○ 子Viewがwrap_content
    ■ RelativeLayoutの余りサイズ + AT_MOST※
    ※余りがなければ0 + UNSPECIFIED

    View Slide

  10. RelativeLayout#onLayout

    View Slide

  11. RelativeLayout#onLayout
    ● measure通りにレイアウトするだけ
    ○ RelativeLayout.LayoutParamsが位置と座標を持つ
    ■ mLeft, mTop, mRight, mBottom
    ● シンプル!

    View Slide

  12. 循環参照の検知

    View Slide

  13. 循環参照の検知
    ● RelativeLayoutで循環参照は禁止
    ○ rightOfのleftOfが自身のような場合
    ○ ConstraintLayoutは一部OK(Chainになる)
    ● グラフの参照で解決

    View Slide

  14. DependencyGraph
    ● mNodes = 子Viewすべて、ArrayList
    ● mKeyNodes = IDを持つ子View、SparseArray
    Node
    ● dependents = 参照しているNode
    ● dependencies = 参照されているNode

    View Slide

  15. DependencyGraph#getSortedViews
    1. GraphのrootをDequeに入れる
    2. Dequeからグラフの頂点のNodeをpoll
    3. 2.を参照している子Nodeに対して
    3.1. 参照されているNodeがないならばDequeに追加
    3.2. 参照されているNodeがあれば何もしない
    4. Dequeが空ならば5、
    Dequeが空でないならば2.に戻る
    5. すべてのEdgeをDequeに追加できていない場合は
    例外を投げる

    View Slide

  16. 循環参照の検知(正常系)
    A
    B
    C
    Dequeue

    View Slide

  17. 循環参照の検知(正常系)
    A
    B
    C
    Dequeue
    A
    1.RootをDequeueに追加

    View Slide

  18. 循環参照の検知(正常系)
    A
    B
    C
    Dequeue
    B
    2.pollして消去
    3.1.Dequeueに追加

    View Slide

  19. 循環参照の検知(正常系)
    B
    C
    Dequeue
    C
    3.1.Dequeueに追加
    2.pollして消去

    View Slide

  20. 循環参照の検知(正常系)
    C
    Dequeue
    2.pollして消去

    View Slide

  21. 循環参照の検知(正常系)
    Dequeue
    5.Dequeueが空で
    すべてのEdgeを参照したので終了

    View Slide

  22. 循環参照の検知(異常系)
    A
    B
    C
    Dequeue
    循環参照

    View Slide

  23. 循環参照の検知(異常系)
    A
    B
    C
    Dequeue
    A
    1.RootをDequeueに追加

    View Slide

  24. 循環参照の検知(異常系)
    A
    B
    C
    Dequeue
    2.pollして消去
    3.2.参照があるので
    Dequeueに追加しない

    View Slide

  25. 循環参照の検知(異常系)
    B
    C
    Dequeue
    5.Dequeueが空なのにすべてのEdgeが参照できていない
    例外を投げる

    View Slide