简体   繁体   中英

LiveData Observer not getting called with kotlin coroutine

I get a file list from remote server then I need to download each of them, after download complete,I should notify UI to display, but livedata observer not get called. I write a demo below,

class MainActivity : AppCompatActivity() {
    val liveData = MutableLiveData<Test>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        liveData.observe(this, Observer {
            Log.d("Test","receive ${it.pos}")
        })


    }

    override fun onResume() {
        super.onResume()

        // example this is a file list 
        for (i in 0..15){
            lifecycleScope.launch {
                withContext(Dispatchers.IO){
                    delay(100)// download file or check file is exits
                    Log.d("Test","send $i")
                    liveData.postValue(Test(i))
                }
            }


        }
    }
}

get log

2020-04-17 12:35:21.847 15449-15490 D/Test: send 2
2020-04-17 12:35:21.848 15449-15491 D/Test: send 3
2020-04-17 12:35:21.849 15449-15495 D/Test: send 0
2020-04-17 12:35:21.853 15449-15491 D/Test: send 5
2020-04-17 12:35:21.873 15449-15490 D/Test: send 1
2020-04-17 12:35:21.873 15449-15496 D/Test: send 4
2020-04-17 12:35:21.876 15449-15491 D/Test: send 6
2020-04-17 12:35:21.883 15449-15449 D/Test: receive 6
2020-04-17 12:35:21.898 15449-15490 D/Test: send 10
2020-04-17 12:35:21.899 15449-15492 D/Test: send 9
2020-04-17 12:35:21.899 15449-15497 D/Test: send 7
2020-04-17 12:35:21.900 15449-15499 D/Test: send 11
2020-04-17 12:35:21.900 15449-15499 D/Test: send 13
2020-04-17 12:35:21.901 15449-15499 D/Test: send 14
2020-04-17 12:35:21.901 15449-15490 D/Test: send 12
2020-04-17 12:35:21.902 15449-15494 D/Test: send 8
2020-04-17 12:35:21.903 15449-15494 D/Test: send 15
2020-04-17 12:35:21.964 15449-15449 D/Test: receive 15

Why only get twice observer onChanged called

Change your onResume() to this:

override fun onResume() {
    super.onResume()

    lifecycleScope.launch {
        withContext(Dispatchers.IO) {
            for (i in 0..15) {
                delay(100)// download file or check file is exits
                Log.d("Test", "send $i")
                liveData.postValue(Test(i))
            }
        }
    }
}

You start 1 coroutine and iterate your file list inside that.

liveData.postValue

If you need set a value from a background thread, you can use postValue(Object)

Posts a task to a main thread to set the given value.

If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.

so everything is ok after change postValue to setValue

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM