Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging LiveData with different Object Contained

So I am writing an app using Room and LiveData. It is a finance app. I have two entities I am trying to merge, Payee and Transaction. Transaction has a ForeignKey linking it to Payee. I am using LiveData from Room all the way through (Daos, Repository, ViewModels) to my UI (Fragments).

I would like to combine these two data sets at some level before I get to the Fragment level but am not sure how to do it. I know I can make a POJO with the Query straight from the database but I kind of want to have a Transaction Object with Payee in it rather than just all the fields from both.

Is there a way to do this? Perhaps using one of the transformations (map or switchMap)? Or maybe using MediatorLiveData? Can they observe more than one data type (eg. LiveData and LiveData)?

Payee.java

@Entity
public class Payee {

    @PrimaryKey (autoGenerate = true)
    @ColumnInfo (name = "id")
    private int id;

    . . . 
}

Transaction.java

@Entity (foreignKeys =
        @ForeignKey(entity = Payee.class, 
                             parentColumns = "id", 
                             childColumns = "payee_id", 
                             onDelete = RESTRICT))
public class Transaction {

    @PrimaryKey (autoGenerate = true)
    @ColumnInfo (name = "id")
    private int id;

    @ColumnInfo (name = "payee_id")
    private int payeeId;
    @Ignore
    private Payee payee;

    . . .
}
like image 766
SSMI Avatar asked Jan 26 '18 04:01

SSMI


1 Answers

The Transaction Object with Payee in it, will be produced by the @Embedded annotation, independently of being additional columns in your DAO query.

There are other scenarios related to your question:

  • Entities that need completely independent queries. A MediatorLiveData with more than one Source will be required.
  • Entities with one-to-many relation that cannot be fulfilled with the default SELECT * FROM query, generated by the @Relation annotation. A Transformations.switchMap can be used as explained below (I found your question while searching for this).

Using global executor pools, as demonstrated in Google GithubBrowserSample sample with the AppExecutor class, the nested query in the repository class will end up like this:

public LiveData<QuotationCustomer> loadQuotationDetails(int quotationId) {
    LiveData<QuotationCustomer> quotationLiveData =
            quotationDao.getQuotationCustomer(quotationId);
    LiveData<QuotationCustomer> result =
            Transformations.switchMap(quotationLiveData, quotation -> {
        MutableLiveData<QuotationCustomer> mutableResult = new MutableLiveData<>();
        appExecutors.diskIO().execute(() -> {
            quotation.quotationDetList = 
                    quotationDetDao.getQuotationDetsByQuotationIdSync(quotationId);
            mutableResult.postValue(quotation);
        });
        return mutableResult;
    });
    return result;
}

In the previous code sample, the getQuotationDetsByQuotationIdSync DAO method is returning a plain List (not a LiveData>) and the QuotationCustomer POJO extends an @Entity annotated class and has the quotationDetList property defined as follows:

@Ignore
public List<QuotationDetProductUnit> quotationDetList;

In your case, replace QuotationCustomer by Payee and QuotationDetProductUnit by Transaction.

like image 185
marioavs Avatar answered Oct 01 '22 02:10

marioavs