我目前正在重构旧代码以使用Android架构组件,并在一种存储库模式中设置房间数据库和排球请求。 因此,表示层/域层要求存储库获取LiveData-Objects以观察或告诉他与服务器同步,之后删除旧的db条目并从服务器重新获取所有当前条目。
我已经为同步部分编写了测试,所以我确信,对象会被正确获取并插入到数据库中。但是,在编写测试以观察该db表的条目时(并测试对象是否正确保存,并且在将它们放入db之前需要完成所有操作),LiveData>我观察,没有被触发。
在下面的代码片段中,您可以假设synchronizeFormsWithServer(...)方法可以正常工作,并且异步执行数据库操作。它包含从db中删除所有Form-Objects的操作,这些操作从服务器获取的Forms列表中不存在并插入所有新的Form-Objects。因为在测试开始时数据库是空的,所以这不应该那么重要
观察者未被触发的测试:
@Test
public void shouldSaveFormsFromServerIntoDb() throws Exception
{
Lifecycle lifecycle = Mockito.mock(Lifecycle.class);
when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED);
LifecycleOwner owner = Mockito.mock(LifecycleOwner.class);
when(owner.getLifecycle()).thenReturn(lifecycle);
final CountDownLatch l = new CountDownLatch(19);
formRepository.allForms().observe(owner, formList ->
{
if (formList != null && formList.isEmpty())
{
for (Form form : formList)
{
testForm(form);
l.countDown();
}
}
});
formRepository.synchronizeFormsWithServer(owner);
l.await(2, TimeUnit.MINUTES);
assertEquals(0, l.getCount());
}
FormRepository代码:
@Override
public LiveData<List<Form>> allForms()
{
return formDatastore.getAllForms();
}
数据存储区:
@Override
public LiveData<List<Form>> getAllForms()
{
return database.formDao().getAllForms();
}
formDao代码(数据库实现了你如何从房间里得到它):
@Query("SELECT * FROM form")
LiveData<List<Form>> getAllForms();
很可能,我对LiveData-Components没有任何了解,因为这是我第一次使用它们,所以也许我得到了一些根本错误的东西。
非常感谢每一点帮助:)
PS:我偶然发现了THIS帖子,该帖子讨论了类似的问题,但由于我目前根本没有使用DI而只使用formrepository的单个实例(只有一个实例) formDao associated)我不认为这是同样的问题。
答案 0 :(得分:7)
好的,所以我找到了解决方案,虽然我不知道,为什么它会这样。
记得当我说“不要担心同步方法”时?好吧......事实证明它存在一些问题,这进一步推迟了解决方案。
我认为最重要的错误是在网络响应进入时更新数据库中对象的方法。 我以前打过电话
@Update
void update(Form form)
在dao中的,由于未知原因不会触发LiveData-Observer。所以我把它改成了
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Form form);
执行此操作后,我可以从我的存储库中获取Form-LiveData,就像
一样简单LiveData<List<Form>> liveData = formRepository.allForms();
然后像往常一样订阅它。 之前失败的测试现在看起来像这样:
@Test
public void shouldSaveFormsFromServerIntoDb() throws Exception
{
Lifecycle lifecycle = Mockito.mock(Lifecycle.class);
when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED);
LifecycleOwner owner = Mockito.mock(LifecycleOwner.class);
when(owner.getLifecycle()).thenReturn(lifecycle);
final CountDownLatch l = new CountDownLatch(19);
final SortedList<Form> sortedForms = new SortedList<Form>(Form.class, new SortedList.Callback<Form>()
{
@Override
public int compare(Form o1, Form o2)
{
return o1.getUniqueId().compareTo(o2.getUniqueId());
}
@Override
public void onChanged(int position, int count)
{
Log.d(LOG_TAG, "onChanged: Form at position " + position + " has changed. Count is " + count);
for (int i = 0; i < count; i++)
{
l.countDown();
}
}
@Override
public boolean areContentsTheSame(Form oldItem, Form newItem)
{
return (oldItem.getContent() != null && newItem.getContent() != null && oldItem.getContent().equals(newItem.getContent())) || oldItem.getContent() == null && newItem.getContent() == null;
}
@Override
public boolean areItemsTheSame(Form item1, Form item2)
{
return item1.getUniqueId().equals(item2.getUniqueId());
}
@Override
public void onInserted(int position, int count)
{
}
@Override
public void onRemoved(int position, int count)
{
}
@Override
public void onMoved(int fromPosition, int toPosition)
{
}
});
LiveData<List<Form>> ld = formRepository.allForms();
ld.observe(owner, formList ->
{
if (formList != null && !formList.isEmpty())
{
Log.d(LOG_TAG, "shouldSaveFormsFromServerIntoDb: List contains " + sortedForms.size() + " Forms");
sortedForms.addAll(formList);
}
});
formRepository.synchronizeFormsWithServer(owner);
l.await(2, TimeUnit.MINUTES);
assertEquals(0, l.getCount());
}
我知道将从服务器获取正好19个表单,然后每个表单将被更改一次(第一次加载包含所有具有减少数据的表单的列表,第二次我再次从服务器加载每个表单带有更多数据的新值的db中的旧值。
我不知道这对你@ joao86是否有帮助,但也许你有类似的问题。如果是这样,请务必在此处发表评论:)
答案 1 :(得分:2)
我和你有类似的问题 - &gt; LiveData is not updating its value after first call
使用MutDataLiveData而不是使用LiveData,并将MutableLiveData<List<Form>>
对象传递给存储库,并对列表的新内容进行setValue
或postValue
。
根据我对此的经验,这并不多,显然观察者已经连接到你首先分配它的对象,并且必须对该对象进行每一次更改。
答案 2 :(得分:1)
您必须在所有地方使用相同的数据库实例。
=>为此使用单例