[Android] FlowBinding:CoroutineFlowを使用して応答性の高いUIを作成する

ここに写真の説明を挿入

RxBinding


今日のAndroid開発では、MVI、Redux、一方向データフローなどの概念がますます導入されており、reactなどのフロントエンドフレームワークのような応答性の高いUI開発エクスペリエンスの実現に努めています。

Jetpack Composeのような急進的なソリューションに目を向けるだけでなく、クライアントにはRxBindingなどのローカル条件に合わせたソリューションもいくつかあります。RxJavaとAndroid Viewの連携により、Observableを使用してOnClickListenerを置き換え、イベント駆動型UI開発をより効率的に実現します。

findViewById<Button>(R.id.button).clicks().subscribe {
    
    
    // handle button clicked
}

FlowBinding


kotlinx.coroutinesは、1.3以降にFlowライブラリを追加しました。これは、RxJavaのcoroutineバージョンと呼ばれるCoroutineScopeでストリーミングデータを応答的に処理できます。これに対応して、RxJava => Flowの優れたプロジェクトが数多くあります。本日紹介されたFlowBindingは、その1つであるRxBindingのFlowバージョンです。

// Platform bindings
implementation "io.github.reactivecircus.flowbinding:flowbinding-android:${flowbinding_version}"
// AndroidX bindings
implementation "io.github.reactivecircus.flowbinding:flowbinding-appcompat:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-core:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-drawerlayout:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-navigation:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-recyclerview:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-swiperefreshlayout:${flowbinding_version}"
implementation "io.github.reactivecircus.flowbinding:flowbinding-viewpager2:${flowbinding_version}"
// Material Components bindings
implementation "io.github.reactivecircus.flowbinding:flowbinding-material:${flowbinding_version}"

FlowBindingは、Android標準コントロールに加えて、AndroidXおよびマテリアルコントロールのさまざまなコントロールもサポートします。

指示

CoroutineScopeでOnClickイベントを監視します。

uiScope.launch {
    
    
    findViewById<Button>(R.id.button)
        .clicks() // this returns a Flow<Unit>
        .collect {
    
    
            // handle button clicked
        }
}

kotlinx-coroutines-core表現launchIn(scope)を単純化するために提供されていscope.launch { flow.collect() }ます。

findViewById<Button>(R.id.button)
    .clicks() // binding API available in flowbinding-android
    .onEach {
    
    
        // handle button clicked
    }
    .launchIn(uiScope)

上記の例のuiScopeは、アクティビティ/フラグメントのライフサイクルと一致するCoroutineScopeを表しており、メモリリークを効果的に回避します。

実際の開発では、androidx.lifecycle:lifecycle-runtime-ktx:2.2.0提供されている拡張属性を使用LifecycleOwner.lifecycleScope: LifecycleCoroutineScopeでき、ライフサイクルonDestroyのスコープ内でコルーチンをキャンセルできます。

class ExampleActivity : AppCompatActivity() {
    
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_example)
        findViewById<Button>(R.id.button)
            .clicks()
            .onEach {
    
    
                // handle button clicked
            }
            .launchIn(lifecycleScope) // provided by lifecycle-runtime-ktx 
            
    }
}

実施原則

実現の原則は比較的単純です。

scope.launch {
    
    
    findViewById<Button>(R.id.button)
        .clicks() // this returns a Flow<Unit>
        .collect {
    
    
            // handle button clicked
        }
}

パスcallbackFlow、コールバックをフローに変換して上記のclicks()メソッドを実装できます

fun View.clicks(): Flow<Unit> = callbackFlow 
    val listener = View.OnClickListener {
    
    
        offer(Unit)
    }
    setOnClickListener(listener)
    awaitClose {
    
     setOnClickListener(null) }
}

awaitClose{}フローの最後に実行されるため、ここで登録を解除して
offer()SendChannelフローの内部使用にデータ送信できますが、フローが閉じている場合、例外がスローされる可能性があるため、例外キャプチャ処理を増やすことができます。

fun <E> SendChannel<E>.safeOffer(value: E) = !isClosedForSend && try {
    
    
    offer(value)
} catch (e: CancellationException) {
    
    
    false
}

全体のコードは次のとおりです。
ここに写真の説明を挿入

やっと


FlowBindingは、Coroutine Flowを使用して応答性の高いUIツールライブラリのセットを作成し、LifecycleScopeと連携して自動ログアウトを実現し、メモリリークを回避します。現在、Kotlinが普及している場合は、RxBindingの代わりにFlowBindingを使用することをお勧めします。これを機会として、RxJavaの代わりにFlowを使用するためのより多くの使用シナリオを検討してください。

おすすめ

転載: blog.csdn.net/vitaviva/article/details/108901144