2023/06/15開催、NIKKEI Tech Talk #8登壇資料です #nikkei_tech_talk タイトルは「トップ画面のRecyclerViewにComposeを一部導入した話」です https://nikkei.connpass.com/event/284090/
2023/6/15日本経済新聞社 Androidチーム 篠原裕矢トップ画面の RecyclerView にCompose を一部導入した話
View Slide
ハッシュタグ #nikkei_tech_talk自己紹介2● 2020 年 4 月に日経入社(新卒 4 年目)● Android チームで日経電子版と紙面ビューアーを開発● ラーメンとカレーと日本酒が好き
ハッシュタグ #nikkei_tech_talk1. 電子版トップ画面構成について2. Jetpack Compose の導入ステップ3. RecyclerView へ Compose を導入する実装方法アジェンダ3
ハッシュタグ #nikkei_tech_talk● 基本的な RecyclerView の仕組み○ onBindViewHolder 、onCreateViewHolder のタイミング● Compose の LazyColumn 、 LazyRow の仕組み● 複雑な UI を Compose で記述する方法今日話さないこと4
ハッシュタグ #nikkei_tech_talk1. 電子版トップ画面構成について2. Jetpack Compose の導入ステップ3. RecyclerView へ Compose を導入する実装方法アジェンダ5
ハッシュタグ #nikkei_tech_talk電子版トップの画面例( RecyclerView )6
ハッシュタグ #nikkei_tech_talk 7現時点でどこが Compose ?
ハッシュタグ #nikkei_tech_talkCompose を導入済みのアイテム8ヘッダー画像バナー
ハッシュタグ #nikkei_tech_talk電子版トップ画面の特徴9● ユーザーの PV 数が最も多い画面の 1 つ● 重要度の高いニュースが並ぶ● 変更頻度が高い● RecyclerView の Adapter で管理する表示アイテムが 20 種類近くある○ 記事、バナー、ヘッダー、広告など
ハッシュタグ #nikkei_tech_talk1. 電子版トップ画面構成について2. Jetpack Compose の導入ステップ3. RecyclerView へ Compose を導入する実装方法アジェンダ10
ハッシュタグ #nikkei_tech_talk 11Android ViewRecyclerViewAndroid ViewAndroid ViewComposeViewRecyclerViewAndroid ViewAndroid ViewComposeViewLazyColumnComposeViewComposeView導入前 部分的導入 完全移行Jetpack Compose の導入ステップ
ハッシュタグ #nikkei_tech_talkJetpack Compose の導入ステップ12Android ViewRecyclerViewAndroid ViewAndroid ViewComposeViewRecyclerViewAndroid ViewAndroid ViewComposeViewLazyColumnComposeViewComposeView紹介導入前 部分的導入 完全移行
ハッシュタグ #nikkei_tech_talkCompose 導入前の構成13● ViewBinding + ListAdapter の構成○ Groupie や Epoxy などのサードパーティライブラリを使わない素の RecyclerView● 表示アイテムのレイアウトはすべて xml で記述○ 20種類近くの表示アイテムあり
ハッシュタグ #nikkei_tech_talkCompose 部分的導入後の構成14● ViewBinding + AbstractComposeView + ListAdapter の構成● 表示アイテムのレイアウトは xml または Compose で記述○ 20種類近くの表示アイテムあり● アイテム管理などの仕組みは RecyclerView を踏襲
ハッシュタグ #nikkei_tech_talkなぜ部分的に導入したか15● Full Compose な画面に一括で変更するには工数がかかる● 複雑な UI のアイテムも多く、変更頻度が高い画面である○ 20種類近くの UI パーツがある○ 最も訪問される画面なのでリスクが高い● Compose の技術潮流に乗るべく、安全に導入して少しずつ移行したい● 作った UI を別の Compose な画面において再利用可能
ハッシュタグ #nikkei_tech_talk1. 電子版トップ画面構成について2. Jetpack Compose の導入ステップ3. RecyclerView へ Compose を導入する実装方法アジェンダ16
ハッシュタグ #nikkei_tech_talk事前準備 〜ライブラリアップデート〜17● Compose UI のバージョンを 1.2.0 以上に上げる● RecyclerView のバージョンを 1.3.0 以上に上げる● dependencies にて下記記述implementation "androidx.compose.ui:ui:1.2.0"implementation "androidx.recyclerview:recyclerview:1.3.0"
ハッシュタグ #nikkei_tech_talk事前準備 〜ライブラリアップデート〜18● RecyclerView と Compose が協調して動作するようになり、View が画面外に移動したときの再利用が効率的になる● 詳しくは各ライブラリのリリースノート👇○ https://developer.android.com/jetpack/androidx/releases/compose-ui#1.2.0-alpha06○ https://developer.android.com/jetpack/androidx/releases/recyclerview#recyclerview-1.3.0-beta01
ハッシュタグ #nikkei_tech_talk事前準備 〜ライブラリアップデート〜19● Compose UI 1.2.0○ RecyclerView などの PoolingContainer を適切に処理するDisposeOnDetachedFromWindowOrReleasedFromPool という新しい ViewCompositionStrategy が追加された● RecyclerView 1.3.0○ PoolingContainer の修正など、Compose UI 1.2.0 に対応したView 再利用の実装
ハッシュタグ #nikkei_tech_talk実装方法 〜 ViewHolder の作成 〜20● ViewBinding 用の ViewHolder と Compose 用の ViewHolder● Compose 用 のViewHolder には AbstractComposeViewを渡すclass ViewBindingHolder(val binding: ViewBinding,) : RecyclerView.ViewHolder(binding.root)class ComposeViewHolder(val abstractComposeView: AbstractComposeView,) : RecyclerView.ViewHolder(abstractComposeView)
ハッシュタグ #nikkei_tech_talk実装方法21● onCreateViewHolder で ViewType に応じてViewBindingHolder or ComposeViewHolder を返すoverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {return when (ViewType.from(viewType)) {ViewType.HEADLINE_ARTICLE -> {val layoutInflater = LayoutInflater.from(parent.context)ViewBindingHolder(ArticleBinding.inflate(layoutInflater, parent, false))}ViewType.HEADLINE_HEADER -> {ComposeViewHolder(HeaderComposeView(parent.context))}}}
ハッシュタグ #nikkei_tech_talk実装方法22● onBindViewHolder で型チェックをする● ViewBindingHolder or ComposeViewHolder で bind処理を実行するoverride fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {val item = getItem(position)when (holder) {is ViewBindingHolder -> holder.bind(item)is ComposeViewHolder -> holder.bind(item)}}
ハッシュタグ #nikkei_tech_talk実装方法23● ヘッダーの ComposeView に定義した bind メソッドを呼ぶfun ComposeViewHolder.bind(item: NewsItem) {// Composeで実装されているRecyclerViewのアイテムがbind対象when (item) {is NewsItem.HeadlineHeader -> {(abstractComposeView as HeaderComposeView).bind(item.headerItem)}is NewsItem.HeadlineBanner -> {(abstractComposeView as BannerComposeView).bind(item.bannerItem)}else -> {}}}
ハッシュタグ #nikkei_tech_talkclass HeaderComposeView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyle: Int = 0,) : AbstractComposeView(context, attrs, defStyle) {private var headerItem by mutableStateOf(null)@Composableoverride fun Content() {AppTheme {Header(headerItem = headerItem,)}}fun bind(headerItem: HeaderItem) {this.headerItem = headerItem}}実装方法 〜 ヘッダーの ComposeView 〜24Content() の中でComposable 関数が書ける
ハッシュタグ #nikkei_tech_talk実装方法25@Composablefun Header(headerItem: HeaderItem?,modifier: Modifier = Modifier,) {// Text、Button、RowなどのComposable関数を自由に書いてレイアウトを作成する}トップ画面以外にもレイアウトを流用できる
ハッシュタグ #nikkei_tech_talkまとめ26● RecyclerView に Compose を導入していく方法を紹介しました● 部分的な導入は実装コストも低いのでぜひ皆さんもやっていきましょう💪● Compose を例としてモダンな技術をプロダクトに入れていくチームの流れがあり、楽しい開発ができます!
ハッシュタグ #nikkei_tech_talk 27ご清聴ありがとうございました