前提
AndroidのViewModel、LiveDataについてです。
ViewModel内の5回ループの中で、スレッドを3秒止めてはLiveData変数をインクリメントし、インクリメントされる毎にLiveData変数の値を画面に表示するつもりで下記のコードを走らせましたら、何も表示されずに15秒が経過し最終結果の5だけが表示されました。(0, 1, 2, 3, 4, 5が画面に順次表示されると期待していました)
不明点・実現したいこと
なぜループ中のLiveData値がMainActivityに伝達されないのでしょうか?
メソッド内でのグローバル変数への代入は、メソッド終了後にメソッド外に反映されるのでしょうか?
この例のように、LiveData変数の値が一定時間毎に変更されるルーチンにおいて、変更時点の値を画面表示するにはどうすればよいでしょうか?
該当のソースコード
kotlin
1class MyViewModel: ViewModel() { 2 private var localInt = 0 3 4 private val _myString = MutableLiveData<String>("") 5 val myString: LiveData<String> get() = _myString 6 7 fun waitAaddXtimes() { 8 _myString.value = localInt.toString() 9 for ( i in 1..5) { 10 try { 11 Thread.sleep(3000L) 12 } catch (e: InterruptedException) { 13 } 14 _myString.value = (++localInt).toString() 15 } 16 } 17}
kotlin
1class MainActivity : AppCompatActivity() { 2 private val myViewModel: MyViewModel by viewModels() 3 4 override fun onCreate(savedInstanceState: Bundle?) { 5 super.onCreate(savedInstanceState) 6 setContentView(R.layout.activity_main) 7 8 val textViewInfo = findViewById<TextView>(R.id.textView01) 9 10 val myViewModel: MyViewModel by viewModels() 11 val myStringObserver = Observer<String> { it -> 12 textViewInfo.text = it 13 } 14 myViewModel.myString.observe(this, myStringObserver) 15 myViewModel.waitAaddXtimes() 16 } 17}
補足情報
(開発環境)
minSdk 30
targetSdk 33
(実行端末 )
Android 11
そのコードでは waitAaddXtimes は UI スレッドで動きますが、UI スレッドを停止 (Thread.sleep など) すると UI は更新されません。
hoshi-takanori様、ありがとうございます。ずいぶん遅いレスポンスで申し訳ございません。
この事例では、ViewModel中のwaitAaddXtimes()内のThread.sleepがUIを更新を止めても、waitAaddXtimes()内でThread.sleepが終わった時に(ループが次のループに移る時に)UIが更新されないのがわからないのですが、ループ内でThread.sleepを使うと、ループが終了するまでUIが止まってしまうものなのでしょうか?
