使用livedata压缩4个或更多异步调用

时间:2018-06-16 14:43:30

标签: java android android-architecture-components android-livedata

有没有办法使用livingata并行运行多个异步调用?

假设我有4个异步调用。我想等到一切都完成后再使用所有4个调用的结果。

我能想到的一种方法是

{
    "compilerOptions": {
        "baseUrl": "./src",
        "moduleResolution": "node", // was not set before, but is the default
        "paths": {
            "@client/*": [
                "client/*",
            ],
            "@suir/*": [ // notice the `/*` at the end
                "../node_modules/semantic-ui-react/dist/commonjs/*", // notice the `/*`
            ],
        },
        // …
    },
    "include": [
        "./src/client/**/*",
    ],
}

有没有更好的方法来解决这种情况?

2 个答案:

答案 0 :(得分:4)

因此,诀窍是使用MediatorLiveData并让其观察每个LiveData对象,并将更改压缩为某种类型的集合。

public static LiveData<ArrayList<Object>> zipLiveData(LiveData<Object>... liveItems){
    final ArrayList<Object> zippedObjects = new ArrayList<>();
    final MediatorLiveData<ArrayList<Object>> mediator = new MediatorLiveData<>();
    for(LiveData<Object> item: liveItems){
        mediator.addSource(item, new Observer<Object>() {
            @Override
            public void onChanged(@Nullable Object o) {
                if(!zippedObjects.contains(o)){
                    zippedObjects.add(o);
                }
                mediator.setValue(zippedObjects);
            }
        });
    }
    return mediator;
}

或者在科特林:

fun zipLiveData(vararg liveItems: LiveData<*>): LiveData<ArrayList<Any>> {
return MediatorLiveData<ArrayList<Any>>().apply {
    val zippedObjects = ArrayList<Any>()
    liveItems.forEach {
        addSource(it, { item ->
            if (! zippedObjects.contains(item as Any)) {
                zippedObjects.add(item)
            }
            value = zippedObjects
        })
    }
}}

此解决方案没有类型安全性。随时根据您的需求进行定制!

答案 1 :(得分:2)

这将使您将3个liveData压缩在一起。如果您需要超过3个,该方法很容易知道。

fun <A,B,C> zippedLiveData(a: LiveData<A>, b: LiveData<B>, c: LiveData<C>): LiveData<Pair<A, Pair<B,C>>> {
        return MediatorLiveData<Pair<A, Pair<B,C>>>().apply {
            var lastA: A? = null
            var lastB: B? = null
            var lastC: C? = null

            fun update() {
                val localLastA = lastA
                val localLastB = lastB
                val localLastC = lastC
                if (localLastA != null && localLastB != null && localLastC != null)
                    this.value = Pair(localLastA, Pair(localLastB, localLastC))
            }

            addSource(a) {
                lastA = it
                update()
            }
            addSource(b) {
                lastB = it
                update()
            }
            addSource(c) {
                lastC = it
                update()
            }
        }
    }