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

FluxアーキテクチャにJetpack Composeを導入してみた / Introducin...

Sansan
December 17, 2021

FluxアーキテクチャにJetpack Composeを導入してみた / Introducing Jetpack Compose to the Flux architecture

■イベント
【YUMEMI x Sansan Tech Meetup】Android開発におけるチャレンジを語る
https://sansan.connpass.com/event/229780/

■登壇概要

タイトル:FluxアーキテクチャにJetpack Composeを導入してみた

登壇者: 技術本部 Mobile Applicationグループ 

古川 真次

▼Sansan Engineering
https://jp.corp-sansan.com/engineering/

Sansan

December 17, 2021
Tweet

More Decks by Sansan

Other Decks in Technology

Transcript

  1. Fluxアーキテクチャに Jetpack Composeを導入してみた 【 Y U M E M I

    x S a n s a n T e c h M e e t u p 】 A n d r o i d 開 発 に お け る チ ャ レ ン ジ を 語 る Sansan株式会社 技術本部 Mobile Applicationグループ プロダクト開発Androidエンジニア 古川 真次
  2. 自己紹介 • 古川 真次(ふるしん) • @furusin_oriver • Sansan,Inc. Android Engineer,

    Team Leader • 大阪府在住 • 趣味:勉強会の主催 ◦ GDG Osaka オーガナイザー ◦ Kansai.kt オーガナイザー
  3. このセッションのきっかけ - サンプル見てもMVVMばっかり - ちまたの勉強会のセッションを見てもMVVMありきばっかり - 「Jetpack Composeの導入のためにアーキテクチャをMVVMに変えまし た」とか見聞きした -

    🤔🤔🤔🤔🤔 - Jetpack Composeが特定のアーキテクチャでしか使えないなんてことは 絶対ないだろう - ようし、SansanはFluxだからFluxで導入した事例を発信しよう←イマココ
  4. • 機能の実装はKotlin(Java)、UIの実装はXMLと別れていた 従来のAndroid UI設計の問題点 MainActivity.kt class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } activity_main.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, World!" /> </androidx.constraintlayout.widget.ConstraintLayout>
  5. • 機能の実装はKotlin(Java)、UIの実装はXMLと別れていた 従来のAndroid UI設計の問題点 MainActivity.kt class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } activity_main.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, World!" /> </androidx.constraintlayout.widget.ConstraintLayout> • KotlinとLayout XMLを行ったり来たりしないといけない • ミスったらKotiln上の状態とLayout XML上の状態がズレる
  6. Jetpack Composeで書いてみよう MainActivity.kt class MainActivity : ComponentActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { JetpackComposeSampleTheme { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { Greeting("Android") } } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
  7. 既存のFlux + DataBinding(ViewBinding)のイメージ class SampleStateStore() : ViewModel() { var data:

    LiveData<SampleState> = MutableLiveData() fun on(action: Action<*>) { when (action) { is SampleAction -> { (data as MutableLiveData<SampleState>).value = action.payload } } } } class SampleActivity sampleStateStore.data.observe(this, { state -> when (state) { is SampleState.Success -> binding.toolbar.title = state.title } })
  8. - 各Composable関数でStoreをobserveAsState()する Jetpack Compose with Flux(置き換え) @Composable fun Greeting() {

    val stateObserver = sampleStateStore.data.observeAsState() when (val sampleState = stateObserver.value) { is SampleState.Success -> Text(text = "Hello ${sampleState.title}!") SampleState.Error -> Text(text = "Hello Android!") } }
  9. - 各Composable関数でStoreをobserveAsState()する Jetpack Compose with Flux(置き換え) @Composable fun Greeting() {

    val stateObserver = sampleStateStore.data.observeAsState() when (val sampleState = stateObserver.value) { is SampleState.Success -> Text(text = "Hello ${sampleState.title}!") SampleState.Error -> Text(text = "Hello Android!") } }
  10. LiveData<T>.observeAsState() @Composable fun <T> LiveData<T>.observeAsState(): State<T?> = observeAsState(value) @Composable fun

    <R, T : R> LiveData<T>.observeAsState(initial: R): State<R> { val lifecycleOwner = LocalLifecycleOwner.current val state = remember { mutableStateOf(initial) } DisposableEffect(this, lifecycleOwner) { val observer = Observer<T> { state.value = it } observe(lifecycleOwner, observer) onDispose { removeObserver(observer) } } return state }
  11. Jetpack Compose with Flux(置き換え) @Composable fun Toolbar() { Surface {

    TopAppBar { val state = sampleStateStore.data.observeAsState() when (val value = state.value) { is SampleState.Success -> { title = value.title } } } } }
  12. - LiveData - LiveData<T>.observeAsState(initial: R): State<R> - Flow - StateFlow<T>.collectAsState(initial:

    R): State<R> - RxJava2 - Observable<T?>?.subscribeAsState(initial: R?) observeAsStateは他にもある
  13. - Using state in Jetpack Compose - observeAsState()してる https://developer.android.com/codelabs/jetpack-compose- state?hl=ja&continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fcompose%3F

    hl%3Dja%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fjetpack-compose-state#3 - Sansan AndroidにおけるFlux移行(Sansan Builders Blog) https://buildersbox.corp-sansan.com/entry/2019/12/13/110000 参考文献