アイリッジ開発者ブログアイリッジ開発者ブログアイリッジに所属するエンジニアが技術情報を発信していきます。Flowは、非同期処理を行うためのライブラリです。Kotlinのコルーチンという機能を発展させたものです。非同期処理とは、コンピュータプログラムの処理方式の一つで、ある処理が完了するまで待たずに、他の処理を実行することができる仕組みです。従来の同期処理では、ある処理が完了するまで、次の処理を実行することができませんでしたが、非同期処理では、複数の処理を同時に実行することができます。ウェブページの読み込みや、アプリ・サーバー間の通信などのように、長時間かかる処理がある場合、従来の同期処理ではユーザーは処理が完了するまで待たなければならず、ユーザーの操作に反応しない状態に陥ってしまいます。非同期処理を使うことで、ユーザーは待つことなく別の操作を実行することができます。一般的に、非同期処理は、マルチスレッドプログラミング、イベント駆動プログラミング、コールバックなどの方法で実装されます。コルーチンを発展させたものです。「Flow」という言葉は、非同期に実行される値のストリームを表すためのもので、いわゆるObservableやPromiseに似た役割を果たします[1]。コールバックだけで非同期処理を実装したら、コールバックが幾重にも重なったり、時間的には連続して行われる処理がコード上ではバラバラの箇所に書かれるなど、見通しが悪くなってしまうデメリットがあります。Flowを用いると、非同期に流れてくるイベントを購読しておき、実際にイベントが発生したらどのような処理をしたいかをその後に記載できます。これにより、直感的かつシンプルな記載となります。composeという最新のUI構築ライブラリと連携することも当然想定されており、簡単に連携することができます。デメリットとしては、独特の用語や概念など覚えることがあるため、学習コストがかかることです。チートシートなどを利用し、これらの用語や概念をざっと把握してしまうのがまずおすすめです。ついてEmitter/Subscriberという概念があります。これは、Flowの基本的な概念で、値を生成するエミッター(Emitter)と、その値を受け取る購読者(Subscriber)から構成されます。Emitterは、コルーチンの挙動と同様に、一つのスレッドで値を生成していきます。生成された値はFlowパイプラインを通じてSubscriberに渡されます。以下は、Emitter/Subscriberの関係を表しています。SubscriberなおProducer/Consumerという言葉が使われることもありますが、これはEmitter/Subscriberとほぼ同様の意味です。ついてFlow、SharedFlow、MutableSharedFlow、StateFlow、MutableStateFlow、callbackFlowといった概念があります。これらは皆エミッターですが、字面からだけでは使い分けるのが難しいため、解説します。[2]Flow非同期で単一の値または複数の値を生成することができるインターフェースです。エラーを発生させるか、または正常に完了させることができる標準的な実装です。他の全てのFlow関連クラスの継承元となっています。いわゆるコールド[4]なエミッターとなっており、サブスクライバが購読を開始するまでは何も動作をしません。複数の購読者がいた場合、それぞれの購読者に対して別々のストリームが生成されることになります。stateIn[6]オペレータを呼ぶことでこれらに変換することができます。Flowを用いた一例を示します。小文字のflow関数を用いてFlowを生成しています。ここではいわゆるフィボナッチ数列を生成してストリームに流しています。}SharedFlow複数のコレクターが共有できる、複数の値を生成することができます。Flowを継承しています。値はブロードキャストされ、すべてのコレクターに配信されます。いわゆるホット[4]なエミッターとなっているので、複数のコレクターから購読されても、複数のストリームが生成されるなどということはありません。常に一つのストリームしかないことになります。そのため、サーバーとの通信など、高価な処理を無駄に何回もやってしまうという事態を防ぐことができます。任意の数のキャッシュを設定することができ、最新の値+キャッシュされた古い値を購読時に取得できます。MutableSharedFlowSharedFlowを継承した型です。SharedFlowと同様に、複数のコレクターが共有できる複数の値を生成することができます。MutableSharedFlowは、emit()関数によって値を生成することができます。emit()関数によって値を生成することができることから、外部からemit()を呼ばれて勝手な操作で思わぬ値を生成させられてしまうことを防ぐ必要があります。そのため、MutableSharedFlowはprivateな変数としておき、外部にはSharedFlowを露出させるのが良いと考えられます。MutableSharedFlowには直接アクセスさせないため、代わりに関数を設けて外部へ公開する。}}StateFlowSharedFlowを継承したクラスになります。特徴としては以下が挙げられます。常に値を一つだけ持っており、複数持つことはない。この値はvalueというプロパティ経由で簡単に取り出せる。以上のような特徴を持つため、UIを描画するためのデータを流す場所として役に立ちます。UIは常に何かを描画しておかないといけないため、最初から最後までたった一つの値を保つことが保証されているStateFlowは都合がいいのです。値の変更を追跡できる単一の値を生成することができます。StateFlowは、ViewModelなどのライフサイクル感知型コンポーネントで使用することができます。生成されたデータは、一度に1つのコレクターにのみ配信されます。emit()関数によって値を生成することができます。使い分けの典型例SharedFlowにデータレイヤーの処理を担当させ、サーバーと通信を行わせるその他、アプリ全般においてデータを伝搬させるにおいても、SharedFlowを使うUIへの反映はStateFlowで行う。いうのが典型的パターンになります[6]ので、コードで一例を示します。APIRepositoryですがMutableSharedFlowを持っています。通信が行われるまでは何もデータがないため、StateFlowと違い初期値を持っていないMutableSharedFlowを使っています。}ViewModel(データ通信の層とUIの層を仲立ちするためのクラス)において、SharedFlowをStateFlowに変換します。これでUI層にデータを見せる準備をしています。}}UI層のメイン画面です。ComposeのStateに変換し、UIとして表示しています。callbackFlowこちらはクラスではなく、Flowを返す関数です。コールバックベースの使いにくいAPIをFlowに変換することができます。生成されたデータは、emit()関数を使用して新しい値を生成することによって、複数のコレクターに配信されます。ASWebAuthentication...2022-10-05リトライ付きの並列処理をPythonで実装するこんにちは。プロダクト開発グループの中野です。Testを使って外形監視を設定するOMOソリューション本部プロダクト開発部の髙田です。移行におけるレプリケーション活用こんにちは。プロダクト開発グループの川口です。5引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。