2021 Sep. 05.
2021 Sep. 03.
参考ページ android ViewModelScopeコルーチンでメインスレッドを停止する方法は? - スタック・オーバーフロー
コルーチンのlaunchブロック内のデータをlauchブロック外に渡すことはできない。
コルーチン内の結果で返り値を決めるBoolean型関数は作れない。
次のコードは不可。launch{}の終了を待たず"return retValue"が返される。
fun foo(): Boolean { lateinit val retValue: Boolean launch(Dispatchers..Default) { retValue = BAR } return retValue }
ViewModel内のコルーチン内の結果でActivityの動作を決める場合は、コルーチン内の結果をLiveDataとし、そのLiveDataをActivity内で受け取ってActivityの動作を決める。
下記コードでは、PassResultViewModel内のworkLongTime()メソッドの真偽をLiveDataのisFinishSuccessに格納し、それをMainActivityで読み込み、isFinishWorkに格納している。
MainActivity.kt
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.TextView import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val textViewOutput = findViewById<TextView>(R.id.textViewOutput) var isFinishWork: Boolean = false // get ViewModel val smbViewModelFactory = PassResultViewModelFactory() val passResultViewModel: PassResultViewModel = ViewModelProvider(this, smbViewModelFactory).get(PassResultViewModel::class.java) // Create Observer val isFinishSuccessObserver = Observer<Boolean> { isFinish -> isFinishWork = isFinish if (isFinishWork) { textViewOutput.setText(R.string._true) } else { textViewOutput.setText(R.string._false) } } // work in ViewModel passResultViewModel.startWork() // set result of method in ViewModel to variable // passResultViewModel.workLongTime(): Booleanの結果が、workLongTime()を呼び出したpassResultViewModel.startWork()の実行後にisFinishWorkに格納される passResultViewModel.isFinishSuccess.observe(this, isFinishSuccessObserver) } }
PassResultViewModel.kt
import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.* class PassResultViewModel: ViewModel() { // LiveDataを設定する private var _isFinishSuccess = MutableLiveData<Boolean>(false) val isFinishSuccess: LiveData<Boolean> get() = _isFinishSuccess fun startWork() { viewModelScope.launch(Dispatchers.Default) { _isFinishSuccess.postValue(workLongTime()) } } suspend fun workLongTime(): Boolean { delay(10000L) return true } override fun onCleared() { super.onCleared() viewModelScope.cancel() } }
PassResultViewModelFactory.kt
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider class PassResultViewModelFactory: ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { return PassResultViewModel() as T } }