質問するログイン新規登録
Android Wear

Android Wearとは、Googleが発表した腕時計型ウェアラブルデバイス(スマートウォッチ)向けのプラットフォームです。GoogleのAndroid OSをベースにしており、情報の入手・管理などを行うことができます。

Q&A

1回答

675閲覧

android開発 ViewModel内のループ内でLiveData変数の値を変更した時のActivityへの反映について

rasum

総合スコア21

Android Wear

Android Wearとは、Googleが発表した腕時計型ウェアラブルデバイス(スマートウォッチ)向けのプラットフォームです。GoogleのAndroid OSをベースにしており、情報の入手・管理などを行うことができます。

0グッド

0クリップ

投稿2022/09/24 13:30

0

0

前提

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2022/09/24 18:14

そのコードでは waitAaddXtimes は UI スレッドで動きますが、UI スレッドを停止 (Thread.sleep など) すると UI は更新されません。
rasum

2022/10/02 10:05

hoshi-takanori様、ありがとうございます。ずいぶん遅いレスポンスで申し訳ございません。 この事例では、ViewModel中のwaitAaddXtimes()内のThread.sleepがUIを更新を止めても、waitAaddXtimes()内でThread.sleepが終わった時に(ループが次のループに移る時に)UIが更新されないのがわからないのですが、ループ内でThread.sleepを使うと、ループが終了するまでUIが止まってしまうものなのでしょうか?
guest

回答1

0

ViewModel中のwaitAddXtimes()内のThread.sleep()が終わってmyStringの値をUIに書き込もうとしても次のThread.sleep()が始まりUIスレッドがブロックされているのでwaitAaddXtimes()のループ毎にはmyStringの値がUIに表示されないのでしょうね。
コルーチンを使った次のコードで正しく動きました。

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 waitAddXtimes() { 8 _myString.value = localInt.toString() 9 viewModelScope.launch { 10 for ( i in 1..5) { 11 delay(3000L) 12 _myString.value = (++localInt).toString() 13 } 14 } 15 } 16}

投稿2022/10/10 06:35

編集2022/10/10 06:37
rasum

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問