我有一个Simple DAO包括CRUD功能
feed entry DAO.Java
@Dao
public interface FeedEntryDAO {
@Query("SELECT * FROM feedEntrys")
LiveData<List<FeedEntry>> getAll();
@Query("SELECT * FROM feedEntrys WHERE uid = :uid LIMIT 1")
LiveData<FeedEntry> findByUid(int uid);
@Insert
void insertAll(FeedEntry... feedEntries);
@Delete
void delete(FeedEntry feedEntry);
@Update
int update(FeedEntry feedEntry);
}
对于select
,可以返回LiveData类型。
在Activity中,代码非常适合选择
viewModel.getFeedEntrys().observe(this,entries -> {...});
但是,当我尝试插入,更新,删除数据时。代码看起来有点难看,每次都会创建一个asynctask。
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.update(feedEntries[0]);
return null;
}
}.execute(feedEntry);
我有2个问题:
感谢任何建议和意见。谢谢。
- 我可以使用LiveData来包装删除,插入,更新呼叫吗?
不,你不能。我写了issue的答案。原因是,LiveData用于通知更改。插入,更新,删除不会触发更改。它将返回已删除的行,插入的ID或受影响的行。即使它看起来很糟糕也没有意义,没有LiveData包裹你的东西。无论如何,在调用之间使用Single这样的东西是有意义的,让操作在RX-Java操作上触发和操作。
如果要触发这些调用,您会在选择查询上观察,该查询会通知您已更新,插入或删除某些/任何数据的LiveData。
- 更好的方法是为删除,插入,更新维护这样的asynctask类?
查看您的示例后,您似乎滥用了(模型/视图/)ViewModel-Pattern。您永远不应该在视图中访问您的存储库。我不确定你是否这样做是因为它在样品中不可见。无论如何,在观察LiveData并获得结果之后,无需在viewModel中将数据更新包装在AsyncTask中。这意味着,你应该总是照顾好
a)查看< - > viewmodel < - >存储库而不是查看< - >存储库和视图< - > viewmodel
和
b)不要尝试使用不需要的线程。默认情况下,在后台线程(@WorkerThread)上观察LiveData(如果没有使用@MainThread注释),并获取ui-thread(@MainThread)中的值。
您也可以在抽象类中使用@Dao注释,因此:
@Dao BaseDao
类,使用抽象方法@Insert insert(entities)
和具体的方法insert(entities, callback)
做那个丑陋的AsyncTask
工作,在@Insert insert(entities)
上调用抽象onBackground
,在onPostExecute
上调用你的回调。FeedEntryDAO
也抽象扩展BaseDao
和@Query
方法摘要。Kotlin的结果使用非常漂亮:
database.entityDao().insert(entities) { ids ->
// success
}
对于第二个问题,还有另一种更适合AsyncTask的替代品;这是使用java Executor
,好消息是你可以使用Executor
的单个实例代替所有CRUD操作的AsyncTask
的多个实例。
演示示例
public class Repository {
private static Repository instance;
private MyDatabase mDatabase;
private Executor mExecutor = Executors.newSingleThreadExecutor();
private Repository(Application application) {
mDatabase = MyDatabase.getInstance(application.getApplicationContext());
}
public static Repository getInstance(Application application) {
if (instance == null) {
instance = new Repository(application);
}
return instance;
}
public void insert(final MyModel model) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
mDatabase.getMyModelDAO().insert(model);
}
});
}
public void update(final MyModel model) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
mDatabase.getMyModelDAO().update(model);
}
});
}
public void delete(final MyModel model) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
mDatabase.getMyModelDAO().delete(model);
}
});
}
}
要使应用程序的UI在数据更改时自动更新,请在查询方法描述中使用LiveData类型的返回值。 Room会生成所有必要的代码,以便在更新数据库时更新LiveData。
@Dao
interface MyDao {
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
fun loadUsersFromRegionsSync(regions: List<String>): LiveData<List<User>>
}
注意:从1.0版开始,Room使用查询中访问的表列表来决定是否更新LiveData的实例。