As the document says about the Livedata#postValue(T):
If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.
But I really need to call postValue() multiple times on a Livedata in a short time. I am designing a application with downloading function. I write the downloading code inside an AndroidViewmodel, and start a new Thread for each asyns downloading task. As soon as each task is completed, it postValue() to a Livedata, so there may be many tasks posting value to the same Livedata at the same time, which resulted that only the last posting works.
Is there anyway to enable me to postValue() multiple times to a Livedata at the same time and ensure all of the relative Observer react to all the posting?
------My code example is as below---------------
In the AndroidViewModel class:
private MutableLiveData<DataHolder_Task> completedTask;
......
public void bulkDownload(List<DataHolder_Task> tasks){
new Thread(new Runnable() {
@Override
public void run() {
for(DataHolder_Task task:tasks)
{
//download() blocks untill task completed
download(task);
completedTask.postValue(task);
}
}
}).start();
}
public MutableLiveData<DataHolder_Task> getCompletedTask() {
if(completedTask==null){
completedTask=new MutableLiveData<>();
}
return completedTask;
}
In an Activity:
androidViewModel.bulkDownload(a_list_of_tasks)
androidViewModel.getCompletedTask().observe(this, new Observer<DataHolder_Task>() {
@Override
public void onChanged(DataHolder_Task task) {
doSomething(task)
}
});
I achieved this by subclass MutableLiveData, add a queue to buffer the bulk live datas, then dispatch one by one to the main thread:
import androidx.lifecycle.MutableLiveData
import java.util.*
class QueuedMutableLiveData<T> : MutableLiveData<T>() {
private val queue = LinkedList<T?>()
override fun setValue(value: T) {
super.setValue(value)
synchronized(queue) {
queue.pollFirst()
queue.peekFirst()?.run {
super.postValue(this)
}
}
}
override fun postValue(value: T?) {
synchronized(queue) {
queue.add(value)
if (queue.size == 1) {
super.postValue(value)
}
}
}
}
You can try to use .setValue() (or .value for Kotlin) instead of .postValue(). Works for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With