首页 > 解决方案 > 在 Livedata 上多次调用 postValue() 将导致仅调度最后一个。有没有其他解决方案?

问题描述

正如文件所说的那样 Livedata#postValue(T)

如果您在主线程执行发布的任务之前多次调用此方法,则只会分派最后一个值。

但我真的需要在短时间内在 Livedata 上多次调用 postValue() 。我正在设计一个具有下载功能的应用程序。我在 AndroidViewmodel 中编写下载代码,并为每个异步下载任务启动一个新线程。一旦每个任务完成,它就会 postValue() 到一个 Livedata,因此可能有许多任务同时向同一个 Livedata 发布 value,导致只有最后一个发布有效。

有没有办法让我同时向 Livedata 多次 postValue() 并确保所有相关的观察者对所有发布做出反应?

------我的代码示例如下---------------

在 AndroidViewModel 类中:

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;
}

在活动中:

    androidViewModel.bulkDownload(a_list_of_tasks)
    androidViewModel.getCompletedTask().observe(this, new Observer<DataHolder_Task>() {
        @Override
        public void onChanged(DataHolder_Task task) {
            doSomething(task)
        }
    });

标签: androidandroid-livedata

解决方案


我通过 subclass 实现了这一点MutableLiveData,添加了一个队列来缓冲批量实时数据,然后一一分派到主线程:

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)
            }
        }
    }
}

推荐阅读