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

詳解 RelativeLayoutの内部実装

Ad449f3f4e595ade283a30c4f66010be?s=47 HiroYUKI Seto
February 03, 2018

詳解 RelativeLayoutの内部実装

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

Ad449f3f4e595ade283a30c4f66010be?s=128

HiroYUKI Seto

February 03, 2018
Tweet

More Decks by HiroYUKI Seto

Other Decks in Technology

Transcript

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

  2. RelativeLayoutのポイント =Graph

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

  4. DependencyGraph • 有向グラフ • mNodes = 子Viewすべて、ArrayList • mKeyNodes =

    IDを持つ子View、SparseArray Node • dependents = 参照しているNode • dependencies = 参照されているNode
  5. RelativeLayout#onMeasure

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

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

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

    仮レイアウト位置が確定できる
  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
  10. RelativeLayout#onLayout

  11. RelativeLayout#onLayout • measure通りにレイアウトするだけ ◦ RelativeLayout.LayoutParamsが位置と座標を持つ ▪ mLeft, mTop, mRight, mBottom

    • シンプル!
  12. 循環参照の検知

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

  14. DependencyGraph • mNodes = 子Viewすべて、ArrayList • mKeyNodes = IDを持つ子View、SparseArray Node

    • dependents = 参照しているNode • dependencies = 参照されているNode
  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に追加できていない場合は 例外を投げる
  16. 循環参照の検知(正常系) A B C Dequeue

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

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

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

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

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

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

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

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

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