简体   繁体   中英

How to fetch data in Room Android using MVVM architecture

So I'm following the MVVM architere where I have a database with banking transactions:

@Database(entities = {Transaction.class}, version = 1, exportSchema = false) @TypeConverters({DateConverter.class}) 
public abstract class TransactionsRoomDatabase extends RoomDatabase {

        public abstract TransactionDao transactionDao();  
        private static volatile TransactionsRoomDatabase INSTANCE;

        private static final int NUMBER_OF_THREADS = 4;
        private static final ExecutorService databaseWriteExecutor =
                Executors.newFixedThreadPool(NUMBER_OF_THREADS);
    
        public static ExecutorService getDatabaseWriteExecutor() {
            return databaseWriteExecutor;
        }
    
        public static TransactionsRoomDatabase getDatabase(final Context context) {
            if (INSTANCE == null) {
                synchronized (TransactionsRoomDatabase.class) {
                    if (INSTANCE == null) {
                        INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                                TransactionsRoomDatabase .class, "database")
                                .build();
                    }
                }
            }
            return INSTANCE;
        } }

I have the Dao class with 2 queries:

@Dao
public interface TransactionDao {
   // first query
    @Query("SELECT * " +
            "FROM transactions_table " +
            "ORDER BY bookingDate, valueDate DESC")
    LiveData<List<Transaction>> getAllTransactions();
  
  // second query that I don't know how to call it in my fragment
    @Query("SELECT * " +
            "FROM transactions_table " +
            "WHERE debtorAccount = :debtorAccount " +
            "ORDER BY valueDate DESC "
    )
    LiveData<List<Transaction>> getTransactionsFiltered(String debtorAccount);

   // insert the list of transactions in databse
   @Insert(onConflict = OnConflictStrategy.REPLACE)
   void insertTransactions(List<Transaction> transactionList);
}

Repository:

public class TransactionRepository {
    private TransactionDao transactionDao;
    private LiveData<List<Transaction>> transactionList;

    public TransactionRepository(Application application) {
        TransactionsRoomDatabase roomDatabase = TransactionsRoomDatabase.getDatabase(application);
        transactionDao = transactionsRoomDatabase.transactionDao();
        transactionList = transactionDao.getAllTransactions();
    }
  
   // get all transactons
   public LiveData<List<Transaction>> getAllTransactions() {
    return transactionList;
   }

   // insert transactions in database using DAO. Are done in another thread so the main thread is not blocked
    public void insertTransactions(List<Transaction> transactionList) {
        TransactionsRoomDatabase.getDatabaseWriteExecutor().execute(() ->       transactionDao.insertTransactions(transactionList));
    }
}

ViewModel:

public class HomeAdvancedViewModel extends AndroidViewModel {
    private TransactionRepository transactionRepository;
    private LiveData<List<Transaction>> allTransactions;

    public HomeAdvancedViewModel(Application application) {
        super(application);
        transactionRepository = new TransactionRepository(application);
        allTransactions = transactionRepository.getAllTransactions();
    }

    public LiveData<List<Transaction>> getAllTransactions() {
        return allTransactions;
    }
}

In the main fragment, I'm populating a recyclerView with all the transactions in the databse:

public class MainFragment extends Fragment {
    private HomeAdvancedViewModel homeAdvancedViewModel;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        homeAdvancedViewModel = new ViewModelProvider(this).get(HomeAdvancedViewModel.class); // define viewModel
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        /* Here I'm using the observable pattern. When transactions in database are changed, I call my setCurrentTransactions(...) function that populates again the recycler view */
        homeAdvancedViewModel.getAllTransactions().observe(getViewLifecycleOwner(), transactions -> setCurrentTransactions(transactionListAdapter, recyclerViewTransactions, transactions));
    }
}

My question is: How can I call the function from DAO

getTransactionsFiltered(String debtorAccount) 

to populate the SAME recyclerView (when some button is pressed)? I cannot have something like

        public void getTransactionsFiltered(String account) {
            TransactionsRoomDatabase.getDatabaseWriteExecutor().execute(() ->       transactionDao.getTransactionsFiltered(account)); // calling the 2nd query in DAO
        }

in my DAO because the queries should be done on another thread (I'm NOT allowed to do it on the main thread), so my DAO cannot return a List of transactions.
Can you provide any help?

ANSWER
This is how I solved it:

Added in Repository class the following function:

public class TransactionRepository {
    private TransactionDao transactionDao;
    private LiveData<List<Transaction>> transactionList;

    public TransactionRepository(Application application) {
        TransactionsRoomDatabase roomDatabase = TransactionsRoomDatabase.getDatabase(application);
        transactionDao = transactionsRoomDatabase.transactionDao();
        transactionList = transactionDao.getAllTransactions();
    }
  
   // get all transactons
   public LiveData<List<Transaction>> getAllTransactions() {
    return transactionList;
   }

   // NEW FUNCTION ADDED
   public LiveData<List<Transaction>> getTransactionsFiltered(String account) {
     return accountsRoomDatabase.transactionDao().getTransactionsFiltered(account);
   }
}

By doing so, the main thread is not blocked. Don't know for sure if it's the best approach, but it solved my problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM