ConstraintLayoutのクラス解説

Google I/O 2018でConstraintLayout2.0が発表されると思いますが、その前に1.1.0の内部実装を読んでおきましょう。

# はじめに
DroidKaigi 2018で[ConstraintLayoutの内部実装に関する発表](https://speakerdeck.com/seto_hi/xiang-jie-viewgroupfalsereiautonei-bu-shi-zhuang?slide=34)をした者です。動画は[こちら](https://t.co/yBVNfrJW9k)。
発表の中ではレイアウトアルゴリズムを**簡単に**紹介することしかできなかったので、もう少し踏み込んだ内容の紹介をしたいと思います。
この記事では各クラスの役割について記述します。

# 環境
ConstraintLayout Ver1.1.0
ConstraintLayoutはbetaのバージョンが1つ上がるだけで内部実装がかなり変わるので、違うバージョンでは参考にならない可能性が高いです。
Ver1.1.0のコードは公開されていないので、逆コンパイルしたコードを読んでいます。
なお、beta-5までなら[こちら](https://android.googlesource.com/platform/frameworks/opt/sherpa/)に公開されています。

# DroidKaigiの内容のおさらい

## ConstraintLayoutの構成
`constraint-layout`ライブラリは`constraint-layout-solver`ライブラリに依存しています。
`constraint-layout`ライブラリには最低限の実装しかなく、レイアウトの複雑な計算のほとんどは`constraint-layout-solver`側で行われています。
また`constraint-layout-solver`はAndroidに依存しておらず、(使おうと思えば)Android以外のプロジェクトにも使い回せるようになっています。

## ConstraintLayoutのレイアウトアルゴリズム
ConstraintLayoutはView同士の関係を一次方程式や一次不等式に見立て、線形計画問題の最適解を求めることでレイアウト位置を決定しています。
線形計画問題の最適解を求めるためにCassowaryという計算アルゴリズムを使っています。
このあたりの詳細は @inamiy さんの[こちらの記事](https://qiita.com/inamiy/items/a6f73438b32896ffa81e)が参考になります。
(iOSのAutoLayoutもConstraintLayoutと同じくCassowaryを使ってレイアウトを解決してます)

# constraint-layout-solverの各クラスの役割
一部重要そうでないクラスは省略します。

## android.support.constraint.solver パッケージ

### ArrayLinkedVariables
ArrayベースのLinked List。高速でメモリ効率が良いらしいです。
`ArrayBackedVariables`と`LinkedVariables`からインスピレーションを受けているそうです。

### ArrayVariables
使っている部分を見つけられず。
ArrayLinkedVariablesから`head`と`last`が取り除かれた実装になっています。

### ArrayRow
線形計画問題の行列の「行」を表現するクラス。
`LinearSystem.Row`を継承しています。

### LinearSystem
線形方程式の最適解を求めるクラス。solverパッケージでも重要なクラスです。
Cassowaryがここに実装されています。

### Metrics
LinearSystemの状態を保持する値クラス。

### SolverVariable
ViewやContainWidgetのレイアウトをLinearSystemで解決するために変換した値を保持するクラス。
最適解の値も保持をします。

## android.support.constraint.solver.widget パッケージ

### ConstraintWidget
Androidフレームワークで言うViewクラス。

### WidgetContainer
Androidフレームワークで言うViewGroupクラス。`ConstraintWidget`を継承しています。

### ConstraintWidgetContainer
Androidフレームワークで言うConstraintLayoutクラス。`WidgetContainer`を継承しています。

### ConstraintHorizontalLayout, ConstraintTableLayout
`constraint-layout`で使われていない秘密のクラス。
ごにょごにょすると[こんな感じ](https://twitter.com/seto_hi/status/962624113331204096)の成果物が得られます。
ConstraintLayout2.0に期待ですね。

### Helper
`constraint-layout`で言うConstraintHelperクラス。

### Barrier
Barrierクラス。`Helper`を継承しています。

### Guideline
Guidelineクラス。`ConstraintWidget`を継承しています。
(他のConstraintWidgetを参照しないため、HelperではなくConstrantWidgetを継承している)

### Chain
`1.1.0-beta2`から追加されたクラス。
Chainクラスを実現するクラス。staticメソッドが2つあるだけ。
各ConstraintWidgetの関係からいい感じにArrayRowを作成してChainを実現しています。

### ConstraintAnchor
ConstraintWidget同士の関係を表すクラス。
`layout_constraintTop_toTopOf`などで定義した「ConstraintWidgetの各辺がどのConstraintWidgetのどの辺の位置に参考にレイアウトするか」の情報を表します。

### Optimizer
レイアウトの最適化を行うクラス。
各ConstraintWidget同士の関係を、LinearSystemで簡単に解けるように最適化します。
DroidKaigi(`1.1.0-beta5`参考)では「簡単なレイアウトを線形計画問題を解かずに計算するクラス」という説明をしましたが、`1.1.0`では動作が変わっています。ご注意ください。

#### Optimizer#checkMatchParent
ConstraintLayoutの子ViewのLayoutParamsが`match_parent`の場合、親と同じ幅or高さになるように設定して最適化します。

#### Optimizer#analyze
ConstraintWidgetの幅や高さが数値で設定されている場合や、`match_constraint`になっている場合に最適化を行います。

#### Optimizer#applyChainOptimized
メソッド名の通り、ChainになっているConstraintWidgetの関係を最適化します。

### ResolutionNode
`1.1.0-beta6`から追加されたクラス。
`ConstraintAnchor`は各辺の接続情報の値クラスでしたが、このクラスは`invalidate`や`resolve`といったメソッドを持ちます。

### ResolutionAnchor
`1.1.0`から追加されたクラス。`ResolutionNode`を継承しています。
各辺の接続情報を`LinearSystem`へ追加したりもします。

### ResolutionDimension
`1.1.0`から追加されたクラス。`ResolutionNode`を継承しています。
`OptimizationLevel`が`dimenstions`の時に使われます。
float型の`value`を持ちます。