この記事を作った動機
Android アプリでネットワーク接続に対応する の続きの記事です。前の記事でやっていたことに関して、進展があったので、とりあえず忘れないうちに記録しようというわけです。
まあ、理解より先に動くことを試していたので、間違ったこととかも書いていること大いにあり得ます。これはあくまで自分の理解を深めるために記事として書いてしまおうという感じです。ご注意ください。(それは他の記事でも言えることですが。。。)
コード
専用クラス(ViewModel)にて
...
class smbOperation1 : ViewModel(){
private val userLiveData = MutableLiveData<String>()
val user: LiveData<String> get() = userLiveData
init {
// trigger user load.
}
fun doAction() {
viewModelScope.launch {
val test = withContext (Dispatchers.IO) {
testSMB()
}
userLiveData.value = test
}
}
...
}
アクティビティ内にて
...
class shareFolderListActivity1 : AppCompatActivity() {
// https://github.com/hierynomus/smbj
private val smb by viewModels<smbOperation1>()
override fun onCreate(savedInstanceState: Bundle?) {
...
val debugTestStart = findViewById<Button>(R.id.debugTestStart)
val debugText = findViewById<TextView>(R.id.resultAndDebugConsole)
smb.user.observe (this){ message: String ->
debugLog(message)
debugText.setText(message)
}
debugTestStart.setOnClickListener{
smb.doAction()
}
}
...
}
わかったこと(現時点での理解)
- LiveData というのを使う方仕組みの方が新しいっぽい
- AsyncTask クラスとは異なる、kotlin 側で用意されたスレッド管理の仕組みを使う方が簡単そう
LiveData
UI と ViewModel クラス間におけるデータの橋渡し的なやり取りを行う。UIスレッド側で監視される変数的なものである。ViewModel クラスのインスタンスのうち、 LiveData に変更があり次第オブザーバー内に登録された処理が実行され、UIが更新される。
- ViewModel 内のメンバ変数として
private val userLiveData = MutableLiveData<String>()
val user: LiveData<String> get() = userLiveData
- Activity 内の onCrete 内にて
val debugTestStart = findViewById<Button>(R.id.debugTestStart)
val debugText = findViewById<TextView>(R.id.resultAndDebugConsole)
smb.user.observe (this){ message: String ->
debugLog(message)
debugText.setText(message)
}
debugTestStart.setOnClickListener{
smb.doAction()
}
coroutines
kotlin で用意された、スレッディングの仕組みだと思う。Android開発においては、例えば、コンテキストとして、以下のようなものが用意されている。
- Dispatchers.Main
- Dispatchers.Default
- Dispatchers.IO
今回は SMB のためにネットワークの処理を行うので、Dispatchers.IO のコンテキストを利用した。
suspend
詳しいことはまだよくわかっていないが、少なくとも susupend 修飾子がついた関数は、同じように susupend 修飾子がついている関数か、viewModelScope.launch
からしか呼び出して、実行することができない。
withContext
withContext
自体は、susupend 関数なので、直接通常の関数から呼び出すことはできない。以下のように、viewModelScope.launch
と併用するのが、一つのwithContext
関数の使い方っぽい。
viewModelScope.launch {
val test = withContext (Dispatchers.IO) {
testSMB()
}
userLiveData.value = test
}
withContext
関数自体は、kotlin 側で用意された、
- Dispatchers.Main
- Dispatchers.Default
- Dispatchers.IO
のどれかのコンテキストを選んで、coroutines の仕組み上で何かしらの処理をさせるためにあるっぽい。
coroutines でも書いたように、今回は、ネットワーク用のスレッドコンテキストとして、Dispatchers.IO を試した。
前の記事
次の記事
今のところなし
参考にしたサイトとか
- android - Why does viewModelScope.launch run on the main thread by default - Stack Overflow
https://stackoverflow.com/questions/62166878/why-does-viewmodelscope-launch-run-on-the-main-thread-by-default (2025年6月21日) - Coroutines on Android (part I): Getting the background | by Sean McQuillan | Android Developers | Medium
https://medium.com/androiddevelopers/coroutines-on-android-part-i-getting-the-background-3e0e54d20bb (2025年6月21日) - launch | kotlinx.coroutines – Kotlin Programming Language
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html (2025年6月21日)