UIが複雑化した「OPENREC」

森篤史氏(以下、森):「Jetpack ComposeでUI Catalog Libraryを作っている話」というタイトルで発表します。森篤史です。

まず自己紹介です。2019年度にサイバーエージェントに新卒で入社して、今3年目です。子会社のCyberZというところで「OPENREC.tv」という動画配信プラットフォームをやっていて、Androidアプリのチームリーダーをやっています。

CyberZのCTO室や、サイバーエージェント全体に次世代マネジメント室という組織があって、最近はAndroidアプリの開発以外に、そういったところでエンジニア組織の課題解決や活性化みたいなことにも取り組んでいます。

最近の活動としては『良いコードとは何か』という、ちょっと図々しいタイトルですが、新卒向けの研修資料を公開したところ、けっこう反響がありました。個人的にもおすすめの記事なので、よかったら目を通してください。もう1つ『詳解 Kotlin Coroutines』という本を「Zenn」で公開しています。こちらも併せてよろしくお願いします。

本編に入ってくのですが、今日は、UI Catalogはいいぞ、という話と、先ほども話に上がったJetpack Composeはいいぞという話をしていきたいなと思います。

まず最初にUI Catalogの導入と、UI Catalogはそもそも何かという話ですね。先ほどのZOZOさんのお話にもあった思うのですが、UIは往々にして複雑化していきます。「OPENREC(OPENREC.tv)」の例でちょっと説明したいと思うのですが、OPENRECもライブ配信と動画アップロードが存在するプラットフォームになっています。

ライブ配信は、ライブ中と配信中とアーカイブと、時系列に沿って状態が変わるので、それぞれのUIも状態によって出し分ける必要があります。

さらに最近、限定配信を追加しました。その限定配信はサブスク(サブスクリプション)といわれる会員に入っている場合、ペイ・パー・ビューという買い切り配信、チケットを持ってる人のみ見られるもの、プレミアム会員が見られるスペシャル番組配信があります。

また、その限定配信でもお試し期間があり「無料お試し公開中」と表示する必要があります。これを見てもらうとわかるとおり、けっこうメンテナンスしていくのは、それなりのコストになります。

さらに、Dark/Lightの対応もしているので、かける2倍、ケースが変わってくることになります。

最近はちょっと落ち着いてきたところがあると思うのですが、Androidは多様なデバイスがつきまとってきます。小さい端末から大きい端末。OSのバージョンもさまざまですし、AndroidTVに対応する必要もあるかもしれません。

こういった中で、安全かつスピーディにUI変更を行いたいというのが、よくある課題感かなと思います。

手動テストがしやすくなる「UI Catalog」

1つの解決策として挙げられるのは、自動テストを回すというところですね。いわゆるInstrumented Test、エミュレータテストでUIを検証して、さらにそれに対してスクリーンショットを撮ってVisual Regression Testといわれる、ピクセル単位で差分を検知するみたいなことも取り組まれています。

しかしこういった自動化というのは、導入だけでなく運用コスト、メンテナンスコストも考えると、けっこうハードルがあるのではないかなと思っています。

そこで、今回紹介するのがUI Catalogという選択肢です。本体のアプリケーションとは別に、コンポーネントやページを登録するアプリケーションを別途作っておきます。これによって何が良くなるかというと、手動テストしやすいかたちになります。

将来的には、Catalogに登録されたコンポーネントに自動テストを行うこともできるので、一石二鳥になるんじゃないかなと思っています。

他のプラットフォームの関係も紹介します。最初にこのUI Catalogが流行ったのはWebなんじゃないかなと思っています。Storybookといわれるけっこう大きな、長く使われているライブラリがあります。それにインスパイアされたかたちでPLAYBOOKといわれるiOSのUI Catalogライブラリがあります。

Androidは、最近あまりなかったかなと僕は思っているのですが、一応ShowcaseといわれるJetpack Compose製のUI Catalog LibraryがAirbnbから出ています。Android Viewを扱え、なおかつよく使われてるものが、未だかつてないというのがあって、作成を決断しました。

UI Catalog Library「Katalog」を作成中

ここからは、作っているUI Catalog Libraryの紹介をしたいと思います。名前は、ここで初めて公開するのですが、Katalogという名前で今絶賛開発中です。CatalogのCがKotlinのKに変わったかたちです。

本当は公開した状態で発表を迎えたかったのですが、ちょっとドキュメント整理が間に合っていないところがあって、今日はチラ見せだけでお願いできたらなと思います。追加情報が気になる方は、ぜひ僕のTwitterをフォローしてお待ちください。できる限り急ぎます。

Katalogの特徴ですが、こういった感じでいろいろなコンポーネントがズラっと並んだUIになっています。けっこうヌルヌル動きます。全部Jetpack Composeで作られているのですが、Viewにも対応しています。

追加は、DSLといわれるcomposeとよく似た記法で、こうやってgroupやcomposeをネストして追加をしていきます。groupを1つ囲うとネストがさらに深くなるので、見た目とコードが一致していてわかりやすいんじゃないかなと思っています。

View、DataBinding、ViewBinding、Fragmentに対応して、それぞれview、binding、fragmentとこんな感じで追加可能です。

UI Catalogを実際にどうやって活用していくか、いくつか例を紹介したいなと思っています。1つ目が早期実装開始するというところです。APIが開発待ちの状態や、細部の仕様が決まりきっていなくてロジックが組めない状態であっても、セル単位でデザインが決まっているところから実装を開始することが容易になります。

もう1つが、UIのリファクタや機能追加を安全にするというところです。まだUI Catalogに追加されていなかったら、それをCatalogに1回追加してから変更や修正を加えることで、比較的安全に変更を加えられるんじゃないかなと思っています。

「Jetpack Compose」を使用した感想

次は、UI Catalogを作るにあたって、Jetpack Composeを使ってみてどうだったのかという話をしていきます。

今回、Jetpack Composeを採用した背景についてお話しします。先ほど、プロダクション導入をどんどんやっていくぞという話があった後で少し悔しい気持ちがあるのですが、プロダクションへの導入は個人的にはまだ抵抗がありました。

一方で、早く試していきたいという気持ちはすごくあったので、こういったデバッグツールなら試しやすいなと思っています。

将来はJetpack Composeで作成したUIもスムーズに同じような方向で追加していきたいので、Jetpack ComposeでUIもViewも対応したライブラリを作ろうと考えました。

Composeで作っていくと、複雑なUIが非常に書きやすいなと感じています。

例えば画面のカルーセル。横スクロールの画面ですね。これを表示するのにセルをきっちり並べてしまうと、スクロールできることがわからないので、ちょっとはみ出して表示したいという要件がたまにあるのですが、これを既存のViewで実装しようとすると、けっこう大変だなあと思っています。Recycler Viewとかもけっこうクセがあります。

先ほども話に上がったLazyRowを使えば、簡単に遅延でViewを表示できるコンポーネントができます。また、BoxWithConstraintsというBoxがさらに拡張されたものが、親の成約を把握してレイアウトすることができるので、親のWidthを取って、それに合わせて子どものセルをどれぐらいの幅で表示するかをけっこう簡単に表示できます。

もう1つはアニメーションの容易性です。この画面遷移もコンポーズで作っているのですが、こういったよくあるアニメーションをKotlinで書けるというのが、メリットだなと思っています。これはAnimatedContentといわれる、けっこう最近追加されたAPIですが、複数のコンテンツをアニメーションありで切り替えるのがけっこうスムーズにできます。

今回はゴリゴリ既存Viewとの共存を試しているのですが、AndroidViewというComposableが用意されていて、Composableの中でAndroidのViewを表示するのは比較的容易です。

ただ、いくつか共存しないところもあったので、ここはもうちょっと調べながら進めようかなと思っています。

あとはFragmentを表示するComposableが用意されていなかったので、ゴリゴリ自作しました。

先ほども何回か話に上がっているのですが、Composeを使ったアーキテクチャは、もう少し検討が必要なんじゃないかなと触りながら考えています。

僕がけっこう悩んでるのはこの2つのポイントです。1つがJetpack Librariesの中のViewModelをどう組み合わせていくかです。

ViewModelは基本、ActivityかFragmentのスコープで付与できるので、Composableの単位にBindingすることが少しめんどくさい状態になっています。

あとは今日ちょうど(※取材当時)α版が発表されたfor Webやfor Desktop、マルチプラットフォームを考えた時に、今のままだとJetpack Librariesは使えません。

そもそもJetpack Composeで作っているのであれば、画面回転時にViewを破棄する必要がないのでは? というのも1つ検討しようと思っています。今回はentry pointのみでシンプルに、1個だけViewModelを作って試しています。

もう1つが、画面遷移の実装です。Fragmentでの画面遷移を実現するためのJetpackのライブラリである、navigationというものがComposeに対応しています。これを使えば比較的簡単に画面遷移も実装できるのですが、遷移の時に渡す式数がstring型ベースなので、せっかくCompose使っているのにちょっともったいないなあと僕はいつも気になっています。

同じくマルチプラットフォームでどうしようというのも問題となります。今回は完全に自作でstateを持って作っています。

今後の展望とまとめ

今後の展望とまとめを最後に話して終わりたいと思います。

Katalogですが、今絶賛開発中なので間もなく公開予定です。(※取材当時)これは公開した後になると思うのですが、検索機能などさらなる機能の拡充にも取り組んでいき、大玉としては、Visual Regression Testとの結合、スクリーンショットテストが簡単にできる仕組みを作りたいなと思っています。あとはマルチプラットフォームも機会があればチャレンジしたいなと思っています。

今日はUI Catalogはいいぞというところと、Jetpack Composeはいいぞいう話をしてきたのですが、最後にもう1個だけ。サイバーエージェント/CyberZはいいぞという話をさせてください。

今回、このKatalogを作るにあたってさまざまな制度を利用しました。いくつか紹介したいのですが、サイバーエージェントのゼミ制度という、特定の研究テーマに沿って業務時間、予算が配分されるというものがあります。

今年からJetpack Composeゼミというのを立ち上げて、こういったライブラリの開発や、導入にあたってのディスカッションを2週に1回行っています。

これはサイバーエージェントのツールですが、GitHub Enterpriseというものに加入していて、部署や子会社横断でソースコード、パッケージを共有できて、これによってコードの議論がすごくしやすいなと思っています。

僕が所属してるCyberZという子会社でも、最近情報発信にすごく力を入れていて、ガチテックDayというのを不定期で開催しています。1日、自身の興味のある技術調査やアウトプットに時間を使えるという日を決めて、合宿みたいに取り組むことをやっています。

もう1つ、テクプットという社内外の技術アウトプットを推奨していて、その月一番良いアウトプットをした人を表彰しようという制度で、アウトプットの活性化をしています。

最後は会社の説明になってしまったのですが、UI Catalog Library、そしてJetpack Compose、そして会社のことに興味を持ってくださった方は、ぜひ私信でも連絡をくださればうれしいなと思っています。ありがとうございました。