約9分で読めます
Android
UdemyでCoroutinesとFlowの講座を受けました
AI が生成した要約です。正確な内容は本文をご確認ください。
要約を読む
非同期処理の理解を深めるためにUdemyの講座を受けました。 その結果、CoroutinesとFlowの基本を英語で学べたことで、Android開発の非同期処理の仕組みが明確になりました。 Kotlinの標準ライブラリに含まれるCoroutinesとFlowを使えば、追加のライブラリを導入する必要がありません。 これにより開発者がコードを書くときに手間が減り、全体の開発スピードが上がりました。 講座ではCallback、RxJava、async/await、withTimeout、withTimeoutOrNullといった非同期処理の方法を学びました。 特にwithTimeoutOrNullはタイムアウト時にnullを返すため、エラー処理がシンプルになり、コードの信頼性が高まりました。 RoomとCoroutinesを組み合わせたデータベース操作では、データが空かを確認し、値があれば挿入する処理を実行しました。 try/catchで例外を捕らえて、データ取得時の失敗を防ぐことで、アプリの安定性が向上しました。 FlowはonStartで初期値を出力し、onCompletionで処理終了をログに記録します。 SharedFlowとStateFlowはFlowの一種ですが、SharedFlowは複数の場所で値を受け取れる点が特徴です。 StateFlowは初期値を持ち、自分で値を取得できるため、UIの状態管理に非常に役立ちます。 1周では内容が基本的で、英語の理解に時間がかかりましたが、2周目で全体の流れを理解すれば、非同期処理の使い方をより自然に使えるようになります。 結果として、開発者が書くコードが短くなり、読みやすさも向上しました。
はじめに
こんにちは!モバイルアプリ開発Gにてmy routeアプリのAndroid側の開発を担当しておりますRomieです。
KINTOテクノロジーズ株式会社(以下KTC)では、Udemy Businessのアカウントを利用して様々な講座を受講することができます!
今回はKotlin Coroutines and Flow for Android Developmentを受講しました。
Androidにおける非同期処理およびCoroutinesとFlowの理解を深めるために基本的な部分をAll Englishで解説していく講座です。
学習した感想
率直な感想は以下の通りです。
- 英語は非常に平坦でわかりやすい
- Androidの用語を除いて難しい単語がほとんどない
ですので、 初学者から抜け出してしっかり非同期処理およびCoroutinesとFlowを勉強されたい方・Androidの基礎とともに英語の勉強もされたい方には非常におすすめです!
印象に残った項目
CoroutinesとFlowは従来の非同期処理と異なりメインスレッド以外で実行され、非同期処理をより簡潔に記述することができます。
また、CoroutinesとFlowはKotlinの標準ライブラリに含まれているため、追加のライブラリを導入する必要がありません。
ここだけ取り上げても非常に大きなメリットがありますね!
全て基本的な形式になりますが、備忘録も兼ねて以下に記載します。
Callback
Callbackは基本的な非同期処理ですね。onResponse/onFailureで処理を分岐させることができます。
exampleCallback1()!!.enqueue(object : Callback<Any> {
override fun onFailure(call: Call<Any>, t: Throwable) {
println("exampleCallback1 : Error - onFailure")
}
override fun onResponse() {
if (response.isSuccessful) {
println("exampleCallback1 : Success")
} else {
println("exampleCallback1 : Error - isSuccessful is false")
}
}
})
RxJava
RxJavaはsubscribeByの中でonSuccess/onErrorで処理を分岐させることができます。
exampleRxJava()
.flatMap { result -> example2() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
println("Success")
},
onError = {
println("Error")
}
)
.addTo(CompositeDisposable())
async/await
async/awaitで非同期処理を行い、awaitAllで結果をまとめて処理を行います。こちらは従来の非同期処理の中でもよく使われる形式ですね。
viewModelScope.launch {
try {
val resultAsyncAwait =
awaitAll(
async { exampleAsyncAwait1() },
async { exampleAsyncAwait2() },
async { exampleAsyncAwait3() }
)
println("Success")
} catch (exception: Exception) {
println("Error")
}
}
viewModelScope.launch {
try {
val resultAsyncAwait = exampleAsyncAwait()
.map { result ->
async { multiExampleAsyncAwait() }
}.awaitAll()
println("Success")
} catch (exception: Exception) {
println("Error")
}
}
withTimeout
withTimeoutではタイムアウト処理を行います。withTimeoutではタイムアウト時に例外が発生します。
viewModelScope.launch {
try {
withTimeout(1000L) {
exampleWithTimeout()
}
println("Success")
} catch (timeoutCancellationException: TimeoutCancellationException) {
println("タイムアウトによるError")
} catch (exception: Exception) {
println("Error")
}
}
withTimeoutOrNull
withTimeoutOrNullもタイムアウト処理ですが、withTimeoutと異なりwithTimeoutOrNullではタイムアウト時にnullを返します。
viewModelScope.launch {
try {
val resultWithTimeoutOrNull = withTimeoutOrNull(timeout) {
exampleWithTimeoutOrNull()
}
if (resultWithTimeoutOrNull != null) {
println("Success")
} else {
println("タイムアウトによるError")
}
} catch (exception: Exception) {
println("Error")
}
}
RoomとCoroutinesによるデータベース操作
RoomとCoroutinesを組み合わせた処理ではデータベースが空かどうかを確認し、データベースに値があればinsertします。
現在のデータベースの値を取得する処理は例外が発生する可能性があるため、try/catchで囲んでいます。
現在Androidの非同期処理ではFlowと共に非常に多くの場面で使われているのではないでしょうか。
viewModelScope.launch {
val resultDatabaseRoom = databaseRoom.exac()
if (resultDatabaseRoom.isEmpty()) {
println("データベースは空です")
} else {
println("データベースに値あり")
}
try {
val examDataList = getValue()
for (resultExam in examDataList) {
database.insert(resultExam)
}
println("Success")
} catch (exception: Exception) {
println("Error")
}
}
Flow
基本的なFlowですね。onStartで初期値をemitし、onCompletionで処理が完了したことをログに出力します。
sealed class UiState {
data object Loading : UiState()
data class Success(val stockList: List<Stock>) : UiState()
data class Error(val message: String) : UiState()
}
val anythingAsLiveData: LiveData<UiState> = anythingDataSource
.map { anyList ->
UiState.Success(anyList) as UiState
}
.onStart {
emit(UiState.Loading)
}
.onCompletion {
Timber.tag("Flow").d("Flow has completed.")
}
.asLiveData()
SharedFlow/StateFlow
SharedFlow/StateFlowはFlowの一種です。stateInでStateFlowに変換します。
FlowとSharedFlowの違いは、Flowがemitされた値を保持しないのに対し、SharedFlowはemitされた値を保持する点です。
StateFlowは他の2つと異なり、初期値を持ち自分自身で値の取得ができます。
SharedFlowはStateFlowと同じように値を保持しますが、複数のコレクターが値を受け取ることができます。
sealed class UiState {
data object Loading : UiState()
data class Success(val stockList: List<Stock>) : UiState()
data class Error(val message: String) : UiState()
}
val anythingAsFlow: StateFlow<UiState> = anythingDataSource
.map { anyList ->
UiState.Success(anyList) as UiState
}
.onCompletion {
Timber.tag("Flow").d("Flow has completed.")
}.stateIn(
scope = viewModelScope,
initialValue = UiState.Loading,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000)
)
まとめ
内容自体は基本的な部分が多いですが、英語での解説が多かったため1周するのに時間がかかりました。
もっと非同期処理の全体像について理解したあとに2周目を行うと理解が深まるかと思います。
2周目では英語の勉強がメインになりそうですが、、
最後までお読みいただきありがとうございました!
関連記事 | Related Posts
We are hiring!
【オープンポジション】「気になる!」方はまずはこちらからご応募ください。/東京・名古屋・大阪・福岡
業務内容国内外のKINTOサービスや、トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、ご経験・ご志向性に応じて配属を決定し、ご活躍いただきます。
【Java/Python】事業や組織の成長に携わるプロダクトエンジニア(AWS環境)/KINTO CXシステム開発G/東京・名古屋
KINTO CXシステム開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO 』を中心とした国内向けサービスのプロジェクト立ち上げから運用保守に至るまでの運営管理を行っています。大手EC、SIer、ベンチャー、Webサービス企業など、さまざまなスペシャリストが集まり、KINTOサービスを開発しています。
Follow Us
KINTOテクノロジーズの最新情報をSNSで発信中!イベント・テックブログ更新情報もお届けします。
