Android Room 通用 DAO
Posted
技术标签:
【中文标题】Android Room 通用 DAO【英文标题】:Android Room Generic DAO 【发布时间】:2018-08-25 14:43:24 【问题描述】:美好的一天 Stack,我正在开发一个使用 android 的 Room 1.0.0 Alpha 5 的 Android 项目,我面临的主要问题是每次我需要从房间调用一个 DAO 时,我需要做这样的事情:
Activity.java:
...
AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "Storage").build();
Table1 table = new Table1();
table.setId(1);
table.setName("Hello");
new AccessDB().execute(1);
/* Generic AccessDB needed */
private class AccessDB extends AsyncTask<Integer,Void,List<Table1>>
@Override
protected List<Table1> doInBackground(Integer... param)
switch(param[0])
case 1:
return db.Table1DAO().create();
case 2:
return db.Table1DAO().read();
return new ArrayList<>();
@Override
protected void onPostExecute(List<Table1> list)
processData(list);
...
我知道我可以从主线程访问 Room DB,这会缩减代码,但我认为这不是一个好习惯,因为这会在每次必须处理数据时锁定活动。
因此,如果我需要从“Table2”插入或读取数据,我将不得不重新做同样的事情,如果我可以将实体类型转换为“T”之类的泛型或类似的东西,那就太好了制作一个通用的“AccessDB”。 但由于我对 Java 不太熟悉......我目前正在努力解决这个问题。
这是实例的一些其他代码。
AppDatabase.java:
@Database(entities = Table1.class, Table2.class, Table3.class, version = 1)
public abstract class AppDatabase extends RoomDatabase
public abstract Table1DAO Table1DAO();
public abstract Table2DAO Table2DAO();
public abstract Table3DAO Table3DAO();
Table1.java:
@Entity
public class Table1
/* setters & getters */
@PrimaryKey(autoGenerate = true)
private int id;
private String name;
Table1DAO.java:
@Dao public interface Table1DAO
@Query("SELECT * FROM Table1")
List<Table1> read(Table1 table);
@Insert(onConflict = OnConflictStrategy.REPLACE)
List<Long> create(Table1... table);
感谢大家的帮助。
【问题讨论】:
【参考方案1】:您可以使用继承并创建一个BaseDao
,它将由您的所有孩子Dao
实现。这样您就不需要一次又一次地编写常用方法。
interface BaseDao<T>
/**
* Insert an object in the database.
*
* @param obj the object to be inserted.
*/
@Insert
fun insert(obj: T)
/**
* Insert an array of objects in the database.
*
* @param obj the objects to be inserted.
*/
@Insert
fun insert(vararg obj: T)
/**
* Update an object from the database.
*
* @param obj the object to be updated
*/
@Update
fun update(obj: T)
/**
* Delete an object from the database
*
* @param obj the object to be deleted
*/
@Delete
fun delete(obj: T)
了解更多信息:https://gist.github.com/florina-muntenescu/1c78858f286d196d545c038a71a3e864#file-basedao-kt
Florina 的原创作品。
【讨论】:
我想到了一个很相似的东西,不过我觉得这样更好,好像也不能有默认查询,但是还是很有帮助的。 我只看到 Kotlin 中 Dao 的继承。它也可以在 Java 中工作,不是吗? 是的,它也适用于 Java;因为 Java 支持继承。【参考方案2】:我对 Akshay Chordiya 的答案进行了一些尝试,但需要添加两个:
能够插入/更新列表 返回值以监控插入/更新是否成功这是我想出的:
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Update
/**
* List of all generic DB actions
* All use suspend to force kotlin coroutine usage, remove if not required
*/
@Dao
interface BaseDao<T>
// insert single
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(obj: T?): Long
// insert List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(obj: List<T>?) : List<Long>
// update List
@Update
suspend fun update(obj: List<T>?): Int
@Dao
interface MyObjectDao : BaseDao<MyObject>
@Query("SELECT * from $TABLE_NAME WHERE $COL_ID = :id")
suspend fun getById(id: Long): MyObject
然后可以这样调用:
val ids = MyObjectDao.insert(objectList)
【讨论】:
那么它会根据来的对象类型来决定Dao吗? 找到了一个有用的例子来说明如何做类似的事情:medium.com/@berryhuang/android-room-generic-dao-27cfc21a4912以上是关于Android Room 通用 DAO的主要内容,如果未能解决你的问题,请参考以下文章
如何为 Android Room 请求制作通用 AsyncTask