Reputation: 933
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?
Upvotes: 0
Views: 1096
Reputation: 933
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
Upvotes: 0