如何使用 MVVM 架构在 Room Android 中获取数据
How to fetch data in Room Android using MVVM architecture
所以我正在关注 MVVM 架构,其中我有一个包含银行交易的数据库:
@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;
} }
我有 Dao class 有 2 个查询:
@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);
}
存储库:
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));
}
}
视图模型:
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;
}
}
在主要片段中,我用数据库中的所有交易填充了一个 recyclerView:
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));
}
}
我的问题是:如何从 DAO 调用函数
getTransactionsFiltered(String debtorAccount)
填充 SAME recyclerView(按下某个按钮时)?我不能有像
这样的东西
public void getTransactionsFiltered(String account) {
TransactionsRoomDatabase.getDatabaseWriteExecutor().execute(() -> transactionDao.getTransactionsFiltered(account)); // calling the 2nd query in DAO
}
在我的 DAO 中,因为查询应该在另一个线程上完成(我 不允许 在主线程上完成),所以我的 DAO 不能 return 交易清单。
你能提供什么帮助吗?
回答
我是这样解决的:
在存储库 class 中添加了以下功能:
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);
}
}
这样做,主线程不会被阻塞。不确定这是否是最佳方法,但它解决了我的问题
所以我正在关注 MVVM 架构,其中我有一个包含银行交易的数据库:
@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;
} }
我有 Dao class 有 2 个查询:
@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);
}
存储库:
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));
}
}
视图模型:
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;
}
}
在主要片段中,我用数据库中的所有交易填充了一个 recyclerView:
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));
}
}
我的问题是:如何从 DAO 调用函数
getTransactionsFiltered(String debtorAccount)
填充 SAME recyclerView(按下某个按钮时)?我不能有像
这样的东西 public void getTransactionsFiltered(String account) {
TransactionsRoomDatabase.getDatabaseWriteExecutor().execute(() -> transactionDao.getTransactionsFiltered(account)); // calling the 2nd query in DAO
}
在我的 DAO 中,因为查询应该在另一个线程上完成(我 不允许 在主线程上完成),所以我的 DAO 不能 return 交易清单。
你能提供什么帮助吗?
回答
我是这样解决的:
在存储库 class 中添加了以下功能:
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);
}
}
这样做,主线程不会被阻塞。不确定这是否是最佳方法,但它解决了我的问题