Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何依次组合两个实时数据?_Android_Observer Pattern_Android Room_Android Architecture Components_Android Livedata - Fatal编程技术网

Android 如何依次组合两个实时数据?

Android 如何依次组合两个实时数据?,android,observer-pattern,android-room,android-architecture-components,android-livedata,Android,Observer Pattern,Android Room,Android Architecture Components,Android Livedata,我有下一个用例:用户来到注册表单,输入姓名、电子邮件和密码,然后点击注册按钮。之后,系统需要检查电子邮件是否被接收,并根据显示的错误消息或创建新用户 我正在尝试使用Room、ViewModel和LiveData来实现这一点。这是一个我试图学习这些组件的项目,我没有远程api,我将把所有东西都存储在本地数据库中 所以我有这些课程: 注册活动 RegisterViewModel 使用者 UsersDAO 用户还原 用户注册服务 所以我的想法是,将有一个监听器连接到register按钮,它将调用R

我有下一个用例:用户来到注册表单,输入姓名、电子邮件和密码,然后点击注册按钮。之后,系统需要检查电子邮件是否被接收,并根据显示的错误消息或创建新用户

我正在尝试使用Room、ViewModel和LiveData来实现这一点。这是一个我试图学习这些组件的项目,我没有远程api,我将把所有东西都存储在本地数据库中

所以我有这些课程:

  • 注册活动
  • RegisterViewModel
  • 使用者
  • UsersDAO
  • 用户还原
  • 用户注册服务
所以我的想法是,将有一个监听器连接到register按钮,它将调用
RegisterViewModel::register()
方法

class RegisterViewModel extends ViewModel {

    //...

    public void register() {
        validationErrorMessage.setValue(null);
        if(!validateInput())
            return;
        registrationService.performRegistration(name.get(), email.get(), password.get());
    }

    //...

}
这就是基本的想法,我还希望
performRegistration
将新创建的用户返回给我

最让我困扰的是,我不知道如何在服务中实现
performRegistration
功能

class UsersRegistrationService {
    private UsersRepository usersRepo;

    //...

    public LiveData<RegistrationResponse<Parent>>  performRegistration(String name, String email, String password) {
         // 1. check if email exists using repository
         // 2. if user exists return RegistrationResponse.error("Email is taken") 
         // 3. if user does not exists create new user and return RegistrationResponse(newUser)
    }
}
因此,我的问题是如何实现
performRegistration()
函数,如何将值传递回视图模型,然后如何将活动从RegisterActivity更改为MainActivity…

在的帮助下,您可以组合来自多个源的结果。下面是如何组合两个来源的示例:

class CombinedLiveData<T, K, S>(source1: LiveData<T>, source2: LiveData<K>, private val combine: (data1: T?, data2: K?) -> S) : MediatorLiveData<S>() {

private var data1: T? = null
private var data2: K? = null

init {
    super.addSource(source1) {
        data1 = it
        value = combine(data1, data2)
    }
    super.addSource(source2) {
        data2 = it
        value = combine(data1, data2)
    }
}

override fun <S : Any?> addSource(source: LiveData<S>, onChanged: Observer<in S>) {
    throw UnsupportedOperationException()
}

override fun <T : Any?> removeSource(toRemove: LiveData<T>) {
    throw UnsupportedOperationException()
}
}
class-CombinedLiveData(source1:LiveData,source2:LiveData,private-val-combine:(data1:T?,data2:K?)->S:MediatorLiveData(){
私有变量数据1:T?=null
私有变量数据2:K?=null
初始化{
super.addSource(source1){
数据1=它
值=联合收割机(数据1、数据2)
}
super.addSource(source2){
数据2=它
值=联合收割机(数据1、数据2)
}
}
重写fun addSource(源:LiveData,onChanged:Observer){
抛出UnsupportedOperationException()
}
覆盖fun removeSource(toRemove:LiveData){
抛出UnsupportedOperationException()
}
}
以下是上述内容的要点,以备将来更新:
何塞·阿尔塞雷卡可能有:

fun blogpostBoilerplateExample(newUser:String):LiveData{
val liveData1=userOnlineDataSource.getOnlineTime(newUser)
val liveData2=userCheckinsDataSource.getCheckins(newUser)
val result=MediatorLiveData()
result.addSource(liveData1){value->
result.value=CombineRelatestData(liveData1、liveData2)
}
result.addSource(liveData2){value->
result.value=CombineRelatestData(liveData1、liveData2)
}
返回结果
}

您可以使用我的助手方法:

val profile = MutableLiveData<ProfileData>()

val user = MutableLiveData<CurrentUser>()

val title = profile.combineWith(user) { profile, user ->
    "${profile.job} ${user.name}"
}

fun <T, K, R> LiveData<T>.combineWith(
    liveData: LiveData<K>,
    block: (T?, K?) -> R
): LiveData<R> {
    val result = MediatorLiveData<R>()
    result.addSource(this) {
        result.value = block(this.value, liveData.value)
    }
    result.addSource(liveData) {
        result.value = block(this.value, liveData.value)
    }
    return result
}
val profile=MutableLiveData()
val user=MutableLiveData()
val title=profile.combineWith(user){profile,user->
“${profile.job}${user.name}”
}
有趣的LiveData.combineWith(
liveData:liveData,
块:(T?,K?)->R
):LiveData{
val result=MediatorLiveData()
result.addSource(此){
result.value=block(this.value,liveData.value)
}
result.addSource(liveData){
result.value=block(this.value,liveData.value)
}
返回结果
}

您可以定义一个方法,该方法将使用MediatorLiveData组合多个LiveData,然后将此组合结果作为元组公开

public class CombinedLiveData2<A, B> extends MediatorLiveData<Pair<A, B>> {
    private A a;
    private B b;

    public CombinedLiveData2(LiveData<A> ld1, LiveData<B> ld2) {
        setValue(Pair.create(a, b));

        addSource(ld1, (a) -> { 
             if(a != null) {
                this.a = a;
             } 
             setValue(Pair.create(a, b)); 
        });

        addSource(ld2, (b) -> { 
            if(b != null) {
                this.b = b;
            } 
            setValue(Pair.create(a, b));
        });
    }
}
公共类组合LiveData2

编辑:嘿,看,我甚至为你制作了一个从2个数组到16个数组的库:

LiveData liveData1=。。。;
LiveData liveData2=。。。;
MediatorLiveData LiveDataMerge=新的MediatorLiveData();
addSource(liveData1,value->livedatamerge.setValue(value));
addSource(liveData2,value->livedatamerge.setValue(value));

我做了一个基于@guness answer的方法。我发现限制两个
LiveData
s是不好的。如果我们想用3怎么办?我们需要为每个案例创建不同的类。因此,我创建了一个类来处理无限量的
LiveData
s

/**
  * CombinedLiveData is a helper class to combine results from multiple LiveData sources.
  * @param liveDatas Variable number of LiveData arguments.
  * @param combine   Function reference that will be used to combine all LiveData data results.
  * @param R         The type of data returned after combining all LiveData data.
  * Usage:
  * CombinedLiveData<SomeType>(
  *     getLiveData1(),
  *     getLiveData2(),
  *     ... ,
  *     getLiveDataN()
  * ) { datas: List<Any?> ->
  *     // Use datas[0], datas[1], ..., datas[N] to return a SomeType value
  * }
  */
 class CombinedLiveData<R>(vararg liveDatas: LiveData<*>,
                           private val combine: (datas: List<Any?>) -> R) : MediatorLiveData<R>() {

      private val datas: MutableList<Any?> = MutableList(liveDatas.size) { null }

      init {
         for(i in liveDatas.indices){
             super.addSource(liveDatas[i]) {
                 datas[i] = it
                 value = combine(datas)
             }
         }
     }
 }
/**
*CombinedLiveData是一个助手类,用于组合来自多个LiveData源的结果。
*@param liveDatas LiveData参数的变量数。
*@param combine函数引用,用于组合所有LiveData结果。
*@param R组合所有LiveData数据后返回的数据类型。
*用法:
*组合livedata(
*getLiveData1(),
*getLiveData2(),
*     ... ,
*getLiveDataN()
*){数据:列表->
*//使用数据[0]、数据[1]、…、数据[N]返回SomeType值
* }
*/
类CombinedLiveData(vararg liveDatas:LiveData,
private-val-combine:(datas:List)->R:MediatorLiveData(){
私有val数据:MutableList=MutableList(liveDatas.size){null}
初始化{
对于(liveDatas.index中的i){
super.addSource(liveDatas[i]){
数据[i]=it
值=组合(数据)
}
}
}
}

如果希望两个值都不为null

fun <T, V, R> LiveData<T>.combineWithNotNull(
        liveData: LiveData<V>,
        block: (T, V) -> R
): LiveData<R> {
    val result = MediatorLiveData<R>()
    result.addSource(this) {
        this.value?.let { first ->
            liveData.value?.let { second ->
                result.value = block(first, second)
            }
        }
    }
    result.addSource(liveData) {
        this.value?.let { first ->
            liveData.value?.let { second ->
                result.value = block(first, second)
            }
        }
    }

    return result
}
fun LiveData.combineWithNotNull(
liveData:liveData,
块:(T,V)->R
):LiveData{
val result=MediatorLiveData()
result.addSource(此){
这个.value?.let{first->
liveData.value?.let{second->
result.value=块(第一,第二)
}
}
}
result.addSource(liveData){
这个.value?.let{first->
liveData.value?.let{second->
result.value=块(第一,第二)
}
}
}
返回结果
}

如果要在构建时创建字段并进行设置(也可以使用
):

val liveData1=MutableLiveData(false)
val liveData2=MutableLiveData(false)
//如果liveData1和liveData2为true,则返回true
val liveDataCombined=MediatorLiveData(){
//初始值
it.value=false
//观察变化
it.addSource(liveData1){newValue->
它是瓦尔
LiveData liveData1 = ...;
 LiveData liveData2 = ...;

 MediatorLiveData liveDataMerger = new MediatorLiveData<>();
 liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
 liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
/**
  * CombinedLiveData is a helper class to combine results from multiple LiveData sources.
  * @param liveDatas Variable number of LiveData arguments.
  * @param combine   Function reference that will be used to combine all LiveData data results.
  * @param R         The type of data returned after combining all LiveData data.
  * Usage:
  * CombinedLiveData<SomeType>(
  *     getLiveData1(),
  *     getLiveData2(),
  *     ... ,
  *     getLiveDataN()
  * ) { datas: List<Any?> ->
  *     // Use datas[0], datas[1], ..., datas[N] to return a SomeType value
  * }
  */
 class CombinedLiveData<R>(vararg liveDatas: LiveData<*>,
                           private val combine: (datas: List<Any?>) -> R) : MediatorLiveData<R>() {

      private val datas: MutableList<Any?> = MutableList(liveDatas.size) { null }

      init {
         for(i in liveDatas.indices){
             super.addSource(liveDatas[i]) {
                 datas[i] = it
                 value = combine(datas)
             }
         }
     }
 }
fun <T, V, R> LiveData<T>.combineWithNotNull(
        liveData: LiveData<V>,
        block: (T, V) -> R
): LiveData<R> {
    val result = MediatorLiveData<R>()
    result.addSource(this) {
        this.value?.let { first ->
            liveData.value?.let { second ->
                result.value = block(first, second)
            }
        }
    }
    result.addSource(liveData) {
        this.value?.let { first ->
            liveData.value?.let { second ->
                result.value = block(first, second)
            }
        }
    }

    return result
}
val liveData1 = MutableLiveData(false)
val liveData2 = MutableLiveData(false)

// Return true if liveData1 && liveData2 are true
val liveDataCombined = MediatorLiveData<Boolean>().also {
    // Initial value
    it.value = false
    // Observing changes
    it.addSource(liveData1) { newValue ->
        it.value = newValue && liveData2.value!!
    }
    it.addSource(selectedAddOn) { newValue ->
        it.value = liveData1.value!! && newValue
    }
}