减少 Room DataBase Repository 中 AsyncTask 的数量
Reduce the number of AsyncTask in Room DataBase Repository
我正在尝试简化存储库中我的代码的行数。
目前我的代码中有很多重复。
网上的很多解决方案只涉及插入一次到table。
我需要在许多 table 上执行 insert()。我想减少重复编写相同的内部 AsyncTask 以将不同的数据插入不同的 table
这是存储库的代码 class
public class CharacterRepository {
private UserDao rUserDao;
private CharacterDao rCharacterDao;
private EquipementDao rEquipementDao;
private LiveData<List<UserDao>> rUserLD;
private LiveData<List<CharacterDao>> rCharacterLD;
private LiveData<List<EquipmentDao>> rEquipmentLD;
// Constructor that handles the database and initialise the member variables
CharacterRepository(Application application){
MyDatabase db = MyDatabase.getDatabase(application);
rUserDao = db.userDao();
rCharacterDao = db.characterDao();
rEquipementDao = db.EquipmentDao();
rUserLD = rUserDao.getAllUser();
rCharacterLD = rCharacterDao.getAllChar();
rEquipmentLD = rEquipementDao.getAllEquip();
}
// Wrapper method that returns cached entities as LiveData
public LiveData<List<UserEntity>> getAllUser(){return rUserLD;}
public LiveData<List<CharEntity>> getAllChar(){return rCharacterLD;}
public LiveData<List<EquipEntity>> getAllEquip(){return rEquipmentLD;}
/*---------------------the start of the problem-------------------*/
//Wrapper method: calling insert on non-UI Thread
public void insert(UserEntity userEntity){new insertUserAsyncTask(rUserDao).execute(userEntity);}
public void insert(CharacterEntity characterEntity){new insertCharacterAsyncTask(rCharacterDao).execute(characterEntity);}
public void insert(EquipmentEntity equipmentEntity){new insertEquipAsyncTask(rCharacterDao).execute(equipmentEntity);}
/*-------------------THIS IS THE PART WHERE I WANT TO REDUCE THE CODE REDUNDANCY THE CODES ARE DOING THE SAME THING-------------------*/
private static class insertUserAsyncTask extends AsyncTask<UserEntity, Void, Void> {
private UserDao mAsyncTaskDao;
insertUserAsyncTask(UserDao dao) {mAsyncTaskDao = dao;}
@Override
protected Void doInBackground(UserEntity... userEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
private static class insertCharacterAsyncTask extends AsyncTask<CharacterEntity, Void, Void> {
private CharacterDao mAsyncTaskDao;
insertCharacterAsyncTask(CharacterDao dao) {mAsyncTaskDao = dao; }
@Override
protected Void doInBackground(CharacterEntity... characterEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
private static class insertEquipAsyncTask extends AsyncTask<, Void, Void> {
private EquipmentDao mAsyncTaskDao;
insertEquipAsyncTask(EquipmentDao dao) {mAsyncTaskDao = dao;}
@Override
protected Void doInBackground(EquipmentEntity... equipmentEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
}
我还有其他插入方法,我也需要调用删除和更新。我不希望代码如此重复
所以,@notTdar 想出了这个解决方案
class 调用 ThreadPoolExecutor。
调用此 class 以执行 Android Room 数据库中的所有 DAO
- 在
onDestroy
中调用cleanResource();
- 在
onPause
中调用shut();
ThreadPoolExecutorHelper.java
public class ThreadPoolExecutorHelper {
private static final String TAG = ThreadPoolExecutorHelper.class.getSimpleName() + " : ";
private static final boolean LOG_DEBUG = false;
private static volatile ThreadPoolExecutorHelper INSTANCE;
private ThreadPoolExecutor mThreadPoolExecutor;
private BlockingQueue<Runnable> mBlockingQueue;
private static final int TASK_QUEUE_SIZE = 12;
//core size, keeps thread : along with running + idle
private static final int CORE_POOL_SIZE = 5;
// pool size
private static final int MAX_POOL_SIZE = 5;
// core pool size exceeds, idle thread will wait for this time before termination.
private static final long KEEP_ALIVE_TIME = 20L;
public static ThreadPoolExecutorHelper getInstance() {
if (LOG_DEBUG) Log.e(TAG, "getInstance: ");
if (INSTANCE == null) {
synchronized (ThreadPoolExecutorHelper.class) {
if (INSTANCE == null) {
INSTANCE = new ThreadPoolExecutorHelper();
}
}
}
return INSTANCE;
}
private ThreadPoolExecutorHelper() {
if (LOG_DEBUG) Log.d(TAG, "ctor: ");
initBlockingQueue();
initThreadPoolExecutor();
}
// submit Runnables
public void submitRunnable(Runnable task) {
if (LOG_DEBUG) Log.d(TAG, "submitRunnable: " + task.getClass().getSimpleName());
//in case, init again, if null.
initBlockingQueue();
initThreadPoolExecutor();
mThreadPoolExecutor.execute(task);
}
// shut the threadpool
public synchronized void shut() {
if (LOG_DEBUG) Log.d(TAG, "shut: ");
if (mThreadPoolExecutor != null) {
mThreadPoolExecutor.shutdown();
try {
mThreadPoolExecutor.awaitTermination(6000L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
if (LOG_DEBUG) Log.w(TAG, "shut: InterruptedException");
mThreadPoolExecutor.shutdownNow();
}
} else {
Log.e(TAG, "shut: mThreadPoolExecutor instance NULL");
}
}
//clean up
public void cleanResources() {
if (LOG_DEBUG) Log.e(TAG, "cleanResources: ");
if (INSTANCE != null) {
if (mThreadPoolExecutor != null) {
mThreadPoolExecutor = null;
}
if (mBlockingQueue != null) {
mBlockingQueue = null;
}
nullifyHelper();
}
}
private static void nullifyHelper() {
if (INSTANCE != null) {
INSTANCE = null;
}
}
private void initBlockingQueue() {
if (mBlockingQueue == null) {
mBlockingQueue = new LinkedBlockingQueue<>(TASK_QUEUE_SIZE);
}
}
private void initThreadPoolExecutor() {
if (mThreadPoolExecutor == null) {
mThreadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
KEEP_ALIVE_TIME, TimeUnit.SECONDS, mBlockingQueue);
}
}
}
在onCreate
(activity)或onViewCreated
(片段)中添加此代码
这将通过调用 getInstance()
来初始化 ThreadPoolExecutorHelper
private void initExecutorHelper() {
if (LOG_DEBUG) Log.d(TAG, "initExecutorHelper: ");
if (mExecutorHelper == null) {
mExecutorHelper = ThreadPoolExecutorHelper.getInstance();
}
}
这是启动线程的insert();
方法
您可以将其更改为从 Room Database
中的 DAO 执行插入、查询、删除任务
public void insert() {
if (LOG_DEBUG) Log.d(TAG, "requestQREntityList: whatKind= " + whatKind);
mExecutorHelper.submitRunnable(() -> {
if (!Thread.interrupted()) {
//request a list or inset something, write your logic.
} else {
if (LOG_DEBUG) Log.e(TAG, "run: Thread is interrupted");
}
});
}
我正在尝试简化存储库中我的代码的行数。 目前我的代码中有很多重复。
网上的很多解决方案只涉及插入一次到table。 我需要在许多 table 上执行 insert()。我想减少重复编写相同的内部 AsyncTask 以将不同的数据插入不同的 table
这是存储库的代码 class
public class CharacterRepository {
private UserDao rUserDao;
private CharacterDao rCharacterDao;
private EquipementDao rEquipementDao;
private LiveData<List<UserDao>> rUserLD;
private LiveData<List<CharacterDao>> rCharacterLD;
private LiveData<List<EquipmentDao>> rEquipmentLD;
// Constructor that handles the database and initialise the member variables
CharacterRepository(Application application){
MyDatabase db = MyDatabase.getDatabase(application);
rUserDao = db.userDao();
rCharacterDao = db.characterDao();
rEquipementDao = db.EquipmentDao();
rUserLD = rUserDao.getAllUser();
rCharacterLD = rCharacterDao.getAllChar();
rEquipmentLD = rEquipementDao.getAllEquip();
}
// Wrapper method that returns cached entities as LiveData
public LiveData<List<UserEntity>> getAllUser(){return rUserLD;}
public LiveData<List<CharEntity>> getAllChar(){return rCharacterLD;}
public LiveData<List<EquipEntity>> getAllEquip(){return rEquipmentLD;}
/*---------------------the start of the problem-------------------*/
//Wrapper method: calling insert on non-UI Thread
public void insert(UserEntity userEntity){new insertUserAsyncTask(rUserDao).execute(userEntity);}
public void insert(CharacterEntity characterEntity){new insertCharacterAsyncTask(rCharacterDao).execute(characterEntity);}
public void insert(EquipmentEntity equipmentEntity){new insertEquipAsyncTask(rCharacterDao).execute(equipmentEntity);}
/*-------------------THIS IS THE PART WHERE I WANT TO REDUCE THE CODE REDUNDANCY THE CODES ARE DOING THE SAME THING-------------------*/
private static class insertUserAsyncTask extends AsyncTask<UserEntity, Void, Void> {
private UserDao mAsyncTaskDao;
insertUserAsyncTask(UserDao dao) {mAsyncTaskDao = dao;}
@Override
protected Void doInBackground(UserEntity... userEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
private static class insertCharacterAsyncTask extends AsyncTask<CharacterEntity, Void, Void> {
private CharacterDao mAsyncTaskDao;
insertCharacterAsyncTask(CharacterDao dao) {mAsyncTaskDao = dao; }
@Override
protected Void doInBackground(CharacterEntity... characterEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
private static class insertEquipAsyncTask extends AsyncTask<, Void, Void> {
private EquipmentDao mAsyncTaskDao;
insertEquipAsyncTask(EquipmentDao dao) {mAsyncTaskDao = dao;}
@Override
protected Void doInBackground(EquipmentEntity... equipmentEntities) {
mAsyncTaskDao.save(params[0]);
return null;
}
}
}
我还有其他插入方法,我也需要调用删除和更新。我不希望代码如此重复
所以,@notTdar 想出了这个解决方案
class 调用 ThreadPoolExecutor。
调用此 class 以执行 Android Room 数据库中的所有 DAO
- 在
onDestroy
中调用 - 在
onPause
中调用
cleanResource();
shut();
ThreadPoolExecutorHelper.java
public class ThreadPoolExecutorHelper {
private static final String TAG = ThreadPoolExecutorHelper.class.getSimpleName() + " : ";
private static final boolean LOG_DEBUG = false;
private static volatile ThreadPoolExecutorHelper INSTANCE;
private ThreadPoolExecutor mThreadPoolExecutor;
private BlockingQueue<Runnable> mBlockingQueue;
private static final int TASK_QUEUE_SIZE = 12;
//core size, keeps thread : along with running + idle
private static final int CORE_POOL_SIZE = 5;
// pool size
private static final int MAX_POOL_SIZE = 5;
// core pool size exceeds, idle thread will wait for this time before termination.
private static final long KEEP_ALIVE_TIME = 20L;
public static ThreadPoolExecutorHelper getInstance() {
if (LOG_DEBUG) Log.e(TAG, "getInstance: ");
if (INSTANCE == null) {
synchronized (ThreadPoolExecutorHelper.class) {
if (INSTANCE == null) {
INSTANCE = new ThreadPoolExecutorHelper();
}
}
}
return INSTANCE;
}
private ThreadPoolExecutorHelper() {
if (LOG_DEBUG) Log.d(TAG, "ctor: ");
initBlockingQueue();
initThreadPoolExecutor();
}
// submit Runnables
public void submitRunnable(Runnable task) {
if (LOG_DEBUG) Log.d(TAG, "submitRunnable: " + task.getClass().getSimpleName());
//in case, init again, if null.
initBlockingQueue();
initThreadPoolExecutor();
mThreadPoolExecutor.execute(task);
}
// shut the threadpool
public synchronized void shut() {
if (LOG_DEBUG) Log.d(TAG, "shut: ");
if (mThreadPoolExecutor != null) {
mThreadPoolExecutor.shutdown();
try {
mThreadPoolExecutor.awaitTermination(6000L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
if (LOG_DEBUG) Log.w(TAG, "shut: InterruptedException");
mThreadPoolExecutor.shutdownNow();
}
} else {
Log.e(TAG, "shut: mThreadPoolExecutor instance NULL");
}
}
//clean up
public void cleanResources() {
if (LOG_DEBUG) Log.e(TAG, "cleanResources: ");
if (INSTANCE != null) {
if (mThreadPoolExecutor != null) {
mThreadPoolExecutor = null;
}
if (mBlockingQueue != null) {
mBlockingQueue = null;
}
nullifyHelper();
}
}
private static void nullifyHelper() {
if (INSTANCE != null) {
INSTANCE = null;
}
}
private void initBlockingQueue() {
if (mBlockingQueue == null) {
mBlockingQueue = new LinkedBlockingQueue<>(TASK_QUEUE_SIZE);
}
}
private void initThreadPoolExecutor() {
if (mThreadPoolExecutor == null) {
mThreadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
KEEP_ALIVE_TIME, TimeUnit.SECONDS, mBlockingQueue);
}
}
}
在onCreate
(activity)或onViewCreated
(片段)中添加此代码
这将通过调用 getInstance()
ThreadPoolExecutorHelper
private void initExecutorHelper() {
if (LOG_DEBUG) Log.d(TAG, "initExecutorHelper: ");
if (mExecutorHelper == null) {
mExecutorHelper = ThreadPoolExecutorHelper.getInstance();
}
}
这是启动线程的insert();
方法
您可以将其更改为从 Room Database
public void insert() {
if (LOG_DEBUG) Log.d(TAG, "requestQREntityList: whatKind= " + whatKind);
mExecutorHelper.submitRunnable(() -> {
if (!Thread.interrupted()) {
//request a list or inset something, write your logic.
} else {
if (LOG_DEBUG) Log.e(TAG, "run: Thread is interrupted");
}
});
}