在不观察的情况下从房间中选择数据
Selecting Data from Room without observing
我需要 select 来自 table 的数据,对其进行处理,然后将其插入另一个 table。这只会在当天第一次打开应用程序时发生,并且不会在 UI 中使用。我不想使用 LiveData,因为它不需要观察,但是当我研究如何做时,大多数人说我应该使用 LiveData。我试过使用 AsyncTask,但出现错误 "Cannot access database on the main thread since it may potentially...."。
这是我的 AsyncTask
的代码
public class getAllClothesArrayAsyncTask extends AsyncTask<ArrayList<ClothingItem>, Void, ArrayList<ClothingItem>[]> {
private ClothingDao mAsyncDao;
getAllClothesArrayAsyncTask(ClothingDao dao) { mAsyncDao = dao;}
@Override
protected ArrayList<ClothingItem>[] doInBackground(ArrayList<ClothingItem>... arrayLists) {
List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray();
ArrayList<ClothingItem> arrayList = new ArrayList<>(clothingList);
return arrayLists;
}
}
这就是我在 activity
中的称呼
mClothingViewModel = new ViewModelProvider(this).get(ClothingViewModel.class);
clothingItemArray = mClothingViewModel.getClothesArray();
这种情况下的最佳做法是什么?
小结:
- Room 确实不允许在主线程上执行任何操作(查询|插入|更新|删除)。您可以在 RoomDatabaseBuilder 上关闭此控件,但最好不要这样做。
- 如果您不关心 UI,您至少可以将您的 ROOM-ish 代码(可运行)放入线程、执行器、AsyncTask 之一(但去年已弃用)。 .. 我在下面放了例子
- 我认为对 DB 的这种一次性操作的最佳实践是协程(对于那些在项目中使用 Kotlin 的人)和 RxJava(对于那些使用 Java 的人,Single|Maybe as return 类型)。它们提供了更多的可能性,但您应该花时间了解这些机制的要点。
- 要观察来自 Room 的数据流,有 LiveData、Coroutines Flow、RxJava (Flowable)。
在启用 lambda 的情况下使用线程切换的几个示例(如果您出于某种目的不想学习更高级的东西):
只是一个线程
new Thread(() -> {
List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray();
// ... next operations
});
执行者
Executors.newSingleThreadExecutor().submit(() -> {
List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray();
// ... next operations
});
异步任务
AsyncTask.execute(() -> {
List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray();
// ... next operations
});
如果你使用 Repository 模式,你可以把所有这些线程切换放在那里
阅读 AsyncTask 弃用后的生活
我需要 select 来自 table 的数据,对其进行处理,然后将其插入另一个 table。这只会在当天第一次打开应用程序时发生,并且不会在 UI 中使用。我不想使用 LiveData,因为它不需要观察,但是当我研究如何做时,大多数人说我应该使用 LiveData。我试过使用 AsyncTask,但出现错误 "Cannot access database on the main thread since it may potentially...."。 这是我的 AsyncTask
的代码 public class getAllClothesArrayAsyncTask extends AsyncTask<ArrayList<ClothingItem>, Void, ArrayList<ClothingItem>[]> {
private ClothingDao mAsyncDao;
getAllClothesArrayAsyncTask(ClothingDao dao) { mAsyncDao = dao;}
@Override
protected ArrayList<ClothingItem>[] doInBackground(ArrayList<ClothingItem>... arrayLists) {
List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray();
ArrayList<ClothingItem> arrayList = new ArrayList<>(clothingList);
return arrayLists;
}
}
这就是我在 activity
中的称呼 mClothingViewModel = new ViewModelProvider(this).get(ClothingViewModel.class);
clothingItemArray = mClothingViewModel.getClothesArray();
这种情况下的最佳做法是什么?
小结:
- Room 确实不允许在主线程上执行任何操作(查询|插入|更新|删除)。您可以在 RoomDatabaseBuilder 上关闭此控件,但最好不要这样做。
- 如果您不关心 UI,您至少可以将您的 ROOM-ish 代码(可运行)放入线程、执行器、AsyncTask 之一(但去年已弃用)。 .. 我在下面放了例子
- 我认为对 DB 的这种一次性操作的最佳实践是协程(对于那些在项目中使用 Kotlin 的人)和 RxJava(对于那些使用 Java 的人,Single|Maybe as return 类型)。它们提供了更多的可能性,但您应该花时间了解这些机制的要点。
- 要观察来自 Room 的数据流,有 LiveData、Coroutines Flow、RxJava (Flowable)。
在启用 lambda 的情况下使用线程切换的几个示例(如果您出于某种目的不想学习更高级的东西):
只是一个线程
new Thread(() -> { List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray(); // ... next operations });
执行者
Executors.newSingleThreadExecutor().submit(() -> { List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray(); // ... next operations });
异步任务
AsyncTask.execute(() -> { List<ClothingItem> clothingList = mAsyncDao.getAllClothesArray(); // ... next operations });
如果你使用 Repository 模式,你可以把所有这些线程切换放在那里