Android 连接表时房间未正确更新记录
Android Room not updating records properly when tables are joined
我有一个 DAO
具有以下查询方法:
@Dao
public interface QuoteDao {
@Query("SELECT * FROM quotes")
LiveData<List<Quote>> getAll();
@Query("SELECT * FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();
@Update
public void update(Quote quote);
}
而Repository
有以下方法:
public class QuoteRepository {
private static final String TAG = "Repo/Quote";
private final QuoteDao quoteDao;
private LiveData<List<Quote>> quotes;
private final long seed = System.currentTimeMillis();
public QuoteRepository(Application application){
quoteDao = DB.getInstance(application).quoteDao();
quotes = Transformations.map(quoteDao.getAll(), quotes -> {
List<Quote> list = new ArrayList<>(quotes);
Collections.shuffle(list, new Random(seed));
return list;
});
Log.d(TAG, "New instance created...");
}
public LiveData<List<Quote>> getQuotes(){
return quotes;
}
public void updateQuote(Quote quote, QuoteRepository.CallBackListener listener){
Future<?> future = DB.databaseWriteExecutor.submit(() -> quoteDao.update(quote));
futureCallback(future, listener);
}
private void futureCallback(Future<?> future, QuoteRepository.CallBackListener listener){
try {
future.get();
if(future.isDone())
listener.onSuccess();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public interface CallBackListener{
void onSuccess();
}
}
我已经用 quoteDao.getAll()
初始化了 LiveData<List<Quote>> quotes
并洗牌了结果。
有了这个,当我尝试更新任何 Quote
对象时,它工作得很好。
但是当我用 quoteDao.getPreferred()
初始化 LiveData<List<Quote>> quotes
时,更新无法正常工作。这是我使用 getPreferred()
:
的方式
public QuoteRepository(Application application){
quoteDao = DB.getInstance(application).quoteDao();
quotes = Transformations.map(quoteDao.getPreferred(), quotes -> {
List<Quote> list = new ArrayList<>(quotes);
Collections.shuffle(list, new Random(seed));
return list;
});
Log.d(TAG, "New instance created...");
}
预期行为
用例:用户可以 add/remove 作为 书签 来自 LiveData<List<Quote>> quotes
的任何 Quote
。 Quote
应该更新两个列表,即 quoteDao.getAll()
和 quoteDao.getPreferred()
。
当前行为
它适用于 quoteDao.getAll()
。
但是当用户尝试为 quoteDao.getPreferred()
中的任何 Quote
添加书签时,它的行为如下:
- 第一次更新时,它在书签中添加了
Quote
。 (例如,更新索引 0 处的对象)
- 在第二次更新时,它会删除以前添加书签的
Quote
并将其替换为当前选定的。 (例如,用索引 1 替换索引 0 处的对象)
- 有时根本不更新,有时会自动反转更新。
如何管理书签?
我在 quotes
table 中有一列名为 bookmark
,它存储 1 和 0为假
当前流程: Activity/Fragment > QuoteViewModel > QuoteRepository > QuoteDao
- 我做错了什么吗?
- 我是否需要任何额外的代码来管理来自
Join Query
的 LiveData
结果?
- 如何解决?
问题出在Query
,我所有实体的主键列被命名为id
.
正在将父项(类别)的 ID 分配给子项(引用)。
我已经替换了这个:
@Query("SELECT * FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();
有了这个:
@Query("SELECT quotes.* FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();
我有一个 DAO
具有以下查询方法:
@Dao
public interface QuoteDao {
@Query("SELECT * FROM quotes")
LiveData<List<Quote>> getAll();
@Query("SELECT * FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();
@Update
public void update(Quote quote);
}
而Repository
有以下方法:
public class QuoteRepository {
private static final String TAG = "Repo/Quote";
private final QuoteDao quoteDao;
private LiveData<List<Quote>> quotes;
private final long seed = System.currentTimeMillis();
public QuoteRepository(Application application){
quoteDao = DB.getInstance(application).quoteDao();
quotes = Transformations.map(quoteDao.getAll(), quotes -> {
List<Quote> list = new ArrayList<>(quotes);
Collections.shuffle(list, new Random(seed));
return list;
});
Log.d(TAG, "New instance created...");
}
public LiveData<List<Quote>> getQuotes(){
return quotes;
}
public void updateQuote(Quote quote, QuoteRepository.CallBackListener listener){
Future<?> future = DB.databaseWriteExecutor.submit(() -> quoteDao.update(quote));
futureCallback(future, listener);
}
private void futureCallback(Future<?> future, QuoteRepository.CallBackListener listener){
try {
future.get();
if(future.isDone())
listener.onSuccess();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public interface CallBackListener{
void onSuccess();
}
}
我已经用 quoteDao.getAll()
初始化了 LiveData<List<Quote>> quotes
并洗牌了结果。
有了这个,当我尝试更新任何 Quote
对象时,它工作得很好。
但是当我用 quoteDao.getPreferred()
初始化 LiveData<List<Quote>> quotes
时,更新无法正常工作。这是我使用 getPreferred()
:
public QuoteRepository(Application application){
quoteDao = DB.getInstance(application).quoteDao();
quotes = Transformations.map(quoteDao.getPreferred(), quotes -> {
List<Quote> list = new ArrayList<>(quotes);
Collections.shuffle(list, new Random(seed));
return list;
});
Log.d(TAG, "New instance created...");
}
预期行为
用例:用户可以 add/remove 作为 书签 来自 LiveData<List<Quote>> quotes
的任何 Quote
。 Quote
应该更新两个列表,即 quoteDao.getAll()
和 quoteDao.getPreferred()
。
当前行为
它适用于 quoteDao.getAll()
。
但是当用户尝试为 quoteDao.getPreferred()
中的任何 Quote
添加书签时,它的行为如下:
- 第一次更新时,它在书签中添加了
Quote
。 (例如,更新索引 0 处的对象) - 在第二次更新时,它会删除以前添加书签的
Quote
并将其替换为当前选定的。 (例如,用索引 1 替换索引 0 处的对象) - 有时根本不更新,有时会自动反转更新。
如何管理书签?
我在 quotes
table 中有一列名为 bookmark
,它存储 1 和 0为假
当前流程: Activity/Fragment > QuoteViewModel > QuoteRepository > QuoteDao
- 我做错了什么吗?
- 我是否需要任何额外的代码来管理来自
Join Query
的LiveData
结果? - 如何解决?
问题出在Query
,我所有实体的主键列被命名为id
.
正在将父项(类别)的 ID 分配给子项(引用)。
我已经替换了这个:
@Query("SELECT * FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();
有了这个:
@Query("SELECT quotes.* FROM quotes " +
"INNER JOIN categories ON categories.id = quotes.category_id " +
"WHERE categories.selected = 1")
LiveData<List<Quote>> getPreferred();