Я анализировал способ чтения и записи ROOM базы данных СИНХРОНИЧЕСКИ без необходимости Поставщика контента или BroadcastReceiver ,Очевидно, что доступ к базе данных должен быть асинхронным. Я нашел решение, которое делает асинхронную задачу прозрачной для программиста, используя
Callable
и
Future
интерфейсы, которые позволяют мне делать прямые вызовы к базе данных в основном потоке, а также из любой другой части приложения.
Преимущество заключается в том, что имеется почти прямой и синхронный доступ кзапрос определен в комнатном интерфейсе DAO, что подразумевает огромное преимущество перед традиционными методами;Я называю это « ЗВОНОК КЛАССА ДЛЯ КОМНАТЫ ».
Мой вопрос: какие недостатки вы видите для простых запросов?
Простой пример. Предположим, мы определили базу данных помещения с таблицей с именем « users » и в ней содержится 3 столбца: «id», «LastName»и «Имя», где вы, что вставлять, обновлять и читать вашу базу данныхинтерфейс вызывается (DB_Dao) с простыми запросами: обновите и прочитайте пользователя:
@Dao
public interface DB_Dao {
@Insert
void insert(DB_Entity data);
@Update
void update(DB_Entity data);
@Query("SELECT * FROM users ORDER BY id ASC")
List<DB_Entity> getAll();
@Query("SELECT * FROM users WHERE id IS :id")
DB_Entity getUserById(int id);
@Query("SELECT COUNT(id) FROM users")
int getCount();
}
Клиентский класс (DB_Client):
public class DB_Client {
private static DB_Client instance;
private final DB myDB;
private DB_Client(Context context) {
myDB = Room.databaseBuilder(context, DB.class, "users").build();
}
public static synchronized DB_Client getInstance(Context context) {
if (instance == null) {
instance = new DB_Client(context);
} else {
if (!instance.myDB.isOpen()) {
instance = new DB_Client(context);
}
}
return instance;
}
инаконец ... База данных комнаты:
@Database(entities = {DB_Entity.class}, version = 1, exportSchema = false)
public abstract class DB extends RoomDatabase {
public abstract DB_Dao myDao();
}
Теперь создайте то, что я называю " CALLABLE CLASS FOR ROOM ", в котором есть все нужные вам статические методы, которые будут вызыватьсяиз любой части вашего приложения. Давайте назовем класс DB_Utilitys .class:
public class DB_Utility {
/**
* Getter example
* Read user
*/
public static DB_Entity getDBUser(final Context context, final int id){
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(1);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, workQueue);
// Initialize the class returned variable
DB_Entity userData = null;
// Define what type of variable the interface will return
Future<DB_Entity> future;
// Execute the Callable async task using the same variable to be returned
future = threadPoolExecutor.submit(new Callable<DB_Entity>() {
@Override
public DB_Entity call() {
// TODO: here you add whatever you want to do with the database
// In this example, the getUserById query
DB_Dao db = DB_Client.getInstance(context).getDB().myDao();
return db.getUserById(id);
}
});
/*
The future interface returns the result to the previously initialized variable "userData",
has soon the room database is fetched in the CALL(). If the query takes more than the
defined here timeout value (500ms), TimeoutException will be called.
(You can change the value of the time out (500ms) depending of your requirements)
*/
try {
userData = future.get(500,TimeUnit.MILLISECONDS);
}
catch (ExecutionException e) {e.printStackTrace();}
catch (InterruptedException e) {e.printStackTrace();}
catch (TimeoutException e) {e.printStackTrace();}
// Clear to avoid out of memory
future.cancel(true);
return userData;
}
/**
* Setter example
* Change row data
*/
public static void updateDBRow(final Context context, final DB_Entity userData){
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(1);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, workQueue);
// In this case we don't need a return value, so use Void for the Future and Callable as
// a returning object
Future<Void> future;
future = threadPoolExecutor.submit(new Callable<Void>() {
@Override
public Void call() {
// TODO: here you add whatever you want to do with the database
// In this example, the update query
DB_Dao db = DB_Client.getInstance(context).getDB().myDao();
db.update(userData);
// Since no return value is requiered, return null.
return null;
}
});
try {
future.get(500,TimeUnit.MILLISECONDS);
}
catch (ExecutionException e) {e.printStackTrace();}
catch (InterruptedException e) {e.printStackTrace();}
catch (TimeoutException e) {e.printStackTrace();}
// Clear to avoid out of memory
future.cancel(true);
}
}
Как его использовать:
private void example(Context context) {
// If you what to read user id 1 information call:
DB_Entity userInfo = DB_Utility.getDBUser(context, 1);
Log.i("mytag", " User last name: " + userInfo.getLastName());
Log.i("mytag", " User name: " + userInfo.getName());
// If you want to change the name of the same user id 1 use:
userInfo.setName("my_new_name");
DB_Utility.updateDBRow(context, userInfo);
}