Slide 1

Slide 1 text

Jetpack Compose さわってみた @tkhs0604 #love_kotlin Kotlin愛好会 vol.14 @ Wantedly, Inc.

Slide 2

Slide 2 text

人生初登壇です

Slide 3

Slide 3 text

● 高橋 健太 ○ kenken | @tkhs0604 ○ https://tkhs0604.hatenablog.com ● Gunosy Inc. ● SI営業→エンジニア(iOS/Android/Web)→Androidエンジニア ● アカペラ ○ 最近ORICON NEWSに少しだけ載りました 自己紹介

Slide 4

Slide 4 text

● 開催日:2019/8/24(土) ● 場 所:東京コンファレンスセンター品川 5F ● (LT枠ですが) 登壇します Kotlin Fest 2019

Slide 5

Slide 5 text

● 自分のことを覚えて帰っていただく← ● Jetpack Composeの使い方を完全に理解していただく 本日のゴール

Slide 6

Slide 6 text

● Jetpack Compose とは ○ 宣言的UIとは ● UI生成までの流れ ● コンポーネントの作成方法 ○ @Composable ○ @Model ● まとめ ● さらに知りたい方へ アジェンダ

Slide 7

Slide 7 text

Jetpack Compose とは

Slide 8

Slide 8 text

● Google I/O 2019 ● Android Jetpack ● Kotlin ● 宣言的UI ○ cf. Flutter、React Native、Litho、Vue.js ● Pre-alpha版 (2019/8/12時点) ○ ⚠大きく変更が入る可能性があります Jetpack Compose とは

Slide 9

Slide 9 text

● Concise and Idiomatic Kotlin ○ Kotlinにより簡潔に記述可能 ● Declarative ○ フレームワークによる描画の最適化 ● Compatible ○ 既存のView (Android API)と併用可能 ● Enable Beautiful Apps ○ Material Designやアニメーションが利用可能 ● Accelerate Development ○ Apply Changes、Live Previewの活用 → 未だなさそう? コアコンセプト

Slide 10

Slide 10 text

● Concise and Idiomatic Kotlin ○ Kotlinにより簡潔に記述可能 ● Declarative ○ フレームワークによる描画の最適化 ● Compatible ○ 既存のView (Android API)と併用可能 ● Enable Beautiful Apps ○ Material Designやアニメーションが利用可能 ● Accelerate Development ○ Apply Changes、Live Previewの活用 → 未だなさそう? Jetpack Compose の コアコンセプト 宣言的?

Slide 11

Slide 11 text

宣言的UIとは 宣言的 命令的 What (何をするか)を記述 How (どのようにするか)を記述 遅延評価 即時評価 // android.widget.Button Button(this).apply { text = "button" setBackgroundColor(Color.BLUE) setOnClickListener { ... } } // androidx.ui.material.Button Button( text = "button", color = +themeColor { Color.Blue }, onClick = { … } )

Slide 12

Slide 12 text

UI生成までの流れ

Slide 13

Slide 13 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } }

Slide 14

Slide 14 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } } ● Activityの拡張関数 ● Root ViewとなるFrameLayoutの準備 ● 引数で受け取ったコンポーネントを Root Viewの直下へ追加

Slide 15

Slide 15 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } } ● 各種リソースへアクセスするための設定 ○ Context ○ Density ○ FocusManager ○ TextInputService ● 引数で受け取ったコンポーネントを AndroidCraneViewへ追加

Slide 16

Slide 16 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } } ● コンポーネントのThemeの設定 ○ TextStyleやColorの設定も関数で行う

Slide 17

Slide 17 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } } ● コンポーネントのAlignの設定 ○ MarginやPaddingの設定も関数で行う

Slide 18

Slide 18 text

Hello World class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { Text( text = "Hello World", style = +themeTextStyle { h3 } ) } } } } } ● Android APIでいうところのTextView +…?

Slide 19

Slide 19 text

コンポーネントの作成方法

Slide 20

Slide 20 text

コンポーネントの作成 ● @Composableを関数に付与することでコンポーネントとして認識 される ● コンポーネントが満たさなければならない条件 ○ 引数で与えられる値以外を操作しない ○ 副作用が生じるようなパラメータは引数で受け取る

Slide 21

Slide 21 text

コンポーネントの作成 @Composable fun CounterWidget() { Column { Text( text = "Count: 0", style = +themeTextStyle { h5 } ) Button( text = "+" ) } }

Slide 22

Slide 22 text

コンポーネントの作成 class SampleActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { Center { CounterWidget() } } } } }

Slide 23

Slide 23 text

● モデルクラスを作成する ○ @Modelをクラスに付与する ● モデルクラスを利用する ○ コンポーネント内で+state関数によって状態管理用の Stateオブジェクトを生成する ● Stateオブジェクトのプロパティが更新されると、 フレームワークによってUIが再描画される 状態を持ったコンポーネントの作成

Slide 24

Slide 24 text

状態を持ったコンポーネントの作成 @Model data class CounterModel( var count: Int ) @Composable fun CounterWidget() { Column { val counter by +state { CounterModel(0) } Text( text = "Count: ${counter.count}", style = +themeTextStyle { h5 } ) Button( text = "+", onClick = { counter.count++ } ) } }

Slide 25

Slide 25 text

状態を持ったコンポーネントの作成 @Model data class CounterModel( var count: Int ) @Composable fun CounterWidget() { Column { val counter by +state { CounterModel(0) } Text( text = "Count: ${counter.count}", style = +themeTextStyle { h5 } ) Button( text = "+", onClick = { counter.count++ } ) } } ● プリミティブ型、String型の場合は val counter = +state { 0 } で呼び出し可能

Slide 26

Slide 26 text

状態を持ったコンポーネントの作成 @Model data class CounterModel( var count: Int ) @Composable fun CounterWidget() { Column { val counter by +state { CounterModel(0) } Text( text = "Count: ${counter.count}", style = +themeTextStyle { h5 } ) Button( text = "+", onClick = { counter.count++ } ) } } ● @Modelの付与されたクラスでないと UIの再描画はされない

Slide 27

Slide 27 text

まとめ

Slide 28

Slide 28 text

● まだまだ資料は全然少ない ● 開発環境も整っていない (AOSPを直接DLするしか現状ない) ● 独特の記法(+state関数など)がところどころあるので、 逐一実装を追って理解するのがしんどい ● 今までkt/javaファイル、layout.xml、attrs.xml、drawable.xmlに書 いていたことを集約できるので、開発が進めば便利になりそうな気 はする ● まだあわてるような時間じゃない 所感

Slide 29

Slide 29 text

さらに知りたい方へ

Slide 30

Slide 30 text

Kotlin Community ● Kotlin Slackへの参加申請 (#composeチャンネル) ○ https://surveys.jetbrains.com/s3/kotlin-slack-sign-up

Slide 31

Slide 31 text

Thank you very much for listening.