1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Kotlin】インスタンス生成時に非同期で StateFlow の初期化を開始する

Last updated at Posted at 2024-11-04

次のようなクラスと suspend 関数があるとする。

class MyData

/**
 * [MyData] オブジェクトを非同期でロードする。
 */
suspend fun loadMyData(): MyData {
    // 省略
}

ここで新たに MyClass クラスを実装したい。
MyClass クラスには MyData を値とする StateFlow をプロパティとして持たせ、
MyClass インスタンス生成時に loadMyData 関数を呼んで
その返値でこのプロパティを初期化したい。

単純に実装するとこうなる。

⚠️改善の余地あり
class MyClass(scope: CoroutineScope) {
    val myData: StateFlow<MyData?>
        get() = _myData
    private val _myData = MutableStateFlow<MyData?>(null)

    init {
        scope.launch {
            loadMyData()
        }
    }
}

しかしこれだと _myDataMutableStateFlow なので
myData が一度だけ初期化される」ことを保証するためには
MyClass クラス全体をみる必要がある。

そこで次のようにする。

class MyClass(scope: CoroutineScope) {
    val myData: StateFlow<MyData?> =
        flow {
            emit(
                loadMyData()
            )
        }
            .stateIn(
                scope,
                // stateIn 実行に flow の購読が開始されるようにする。
                SharingStarted.Eagerly,
                initialValue = null,
            )
}

これであれば myData プロパティが一度だけ初期化されることが、プロパティの定義だけで保証される。

なお loadMyData が例外をスローすることがある場合(MyClass だけでは復帰処理などができない場合)は
StateFlow の値を Resultにするとよいだろう。

class MyClass(scope: CoroutineScope) {
    val myData: StateFlow<Result<MyData>?> =
        flow {
            emit(
                runCatching {
                    loadMyData()
                }
            )
        }
            .stateIn(
                scope,
                // stateIn 実行に flow の購読が開始されるようにする。
                SharingStarted.Eagerly,
                initialValue = null,
            )
}

Result 型および runCatching 関数についてはこちらも参考にされたい。

/以上

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?