是否可以制作两个 LiveData 的一个 LiveData?

beg*_*992 9 android android-room android-livedata

我有两个 DAO、两个存储库和两个 POJO。有什么方法可以创建一个两个的 Livedata?我需要它为 Recyclerview 制作单个列表。POJO 是类似的对象。

费用库:

public class ExpenseRepository {

private ExpenseDao expenseDao;
private LiveData<List<Expense>> allExpenses;

public ExpenseRepository(Application application) {
    ExpenseIncomeDatabase database = ExpenseIncomeDatabase.getInstance(application);
    expenseDao = database.expenseDao();
    allExpenses = expenseDao.getExpensesByDay();
}

public LiveData<List<Expense>> getAllExpensesByDay() {
    return allExpenses;
}
Run Code Online (Sandbox Code Playgroud)

收入库:

public class IncomeRepository {

private IncomeDao incomeDao;
private LiveData<List<Income>> allIncomes;

public IncomeRepository(Application application) {
    ExpenseIncomeDatabase database = ExpenseIncomeDatabase.getInstance(application);
    incomeDao = database.incomeDao();
    allIncomes = incomeDao.getIncomesByDay();
}

public LiveData<List<Income>> getAllIncomesByDay() {
    return allIncomes;
}
Run Code Online (Sandbox Code Playgroud)

费用道:

@Dao
public interface ExpenseDao {

@Query("SELECT * FROM expense_table ORDER BY day") 
LiveData<List<Expense>> getExpensesByDay();
Run Code Online (Sandbox Code Playgroud)

收入道:

@Dao
public interface IncomeDao {

@Query("SELECT * FROM income_table ORDER BY day") 
LiveData<List<Income>> getIncomesByDay();
Run Code Online (Sandbox Code Playgroud)

DailyViewModel:

public class DailyFragmentViewModel extends AndroidViewModel {

private ExpenseRepository expenseRepository;
private IncomeRepository incomeRepository;
private LiveData<Pair<List<Expense>, List<Income>>> combined;
private ExpenseDao expenseDao;
private IncomeDao incomeDao;

public DailyFragmentViewModel(@NonNull Application application) {
    super(application);
    expenseRepository = new ExpenseRepository(application);
    incomeRepository = new IncomeRepository(application);
    combined = new DailyCombinedLiveData(expenseDao.getExpensesByDay(), incomeDao.getIncomesByDay());
}

public LiveData<Pair<List<Expense>, List<Income>>> getExpensesAndIncomes() {
    return combined;
}
Run Code Online (Sandbox Code Playgroud)

Epi*_*rce 13

我想你想把它们结合起来,是吗?您将需要一个 MediatorLiveData,但是那个说您现在需要 Object 的人是错误的。你需要的是一个MediatorLiveData<Pair<List<Expense>, List<Income>>>.

public class CombinedLiveData extends MediatorLiveData<Pair<List<Expense>, List<Income>>> {
    private List<Expense> expenses = Collections.emptyList();
    private List<Income> incomes = Collections.emptyList();

    public CombinedLiveData(LiveData<List<Expense>> ld1, LiveData<List<Income>> ld2) {
        setValue(Pair.create(expenses, incomes));

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

        addSource(ld2, incomes -> { 
            if(incomes != null) {
                this.incomes = incomes;
            } 
            setValue(Pair.create(expenses, incomes));
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能会使其成为通用的,它将是combineLatest使用 2-arity (Pair) 元组的两个 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));
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,我无法将和设置Collections.emptyList()为 和 的初始值,A并且当您访问该对中的数据时B,您将需要检查nulls。

编辑:您可以使用库https://github.com/Zhuinden/livedata-combinetuple-kt (Kotlin) 或https://github.com/Zhuinden/livedata-combineutil-java/ (Java) 做同样的事情.


iam*_*sal 3

在 kotlin 中创建了这个扩展函数

fun <A, B> LiveData<A>.zipWith(stream: LiveData<B>): LiveData<Pair<A, B>> {
 val result = MediatorLiveData<Pair<A, B>>()
  result.addSource(this) { a ->
    if (a != null && stream.value != null) {
        result.value = Pair(a, stream.value!!)
    }
  }
 result.addSource(stream) { b ->
    if (b != null && this.value != null) {
        result.value = Pair(this.value!!, b)
    }
 }
 return result
}
Run Code Online (Sandbox Code Playgroud)