更新数据库时实时数据列表不更新



我目前正在重构旧版代码以使用Android体系结构组件,并在一种存储库模式下设置房间DB和凌空请求。因此,演示文稿/域层要求存储库使Livedata-Objects观察或告诉他与服务器同步,然后删除旧的DB条目,所有当前的DB条目都从服务器中撤离。

我已经为同步部分编写了测试,因此我敢肯定,将对象正确获取并插入数据库。但是,当编写测试以观察DB表的条目时(并测试是否正确保存对象,并在将它们放入DB之前需要完成所有操作)我要观察到的LIVEDATA>我要观察到,不会触发。/p>

在以下片段中,您可以假设,SynchronizeFormSwithServer(...)方法确实可以正常工作,并且正在异步执行数据库操作。它包含从DB中删除所有形式的操作,这些操作从服务器列出的表单列表中不存在,并插入所有新的形式。由于在测试开始时,数据库是空的,这应该没关系

观察者没有触发的测试:

  @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:我偶然发现了这篇文章,该帖子讨论了一个类似的问题,但是由于我目前根本不使用di,只使用formrepository的一个实例(只有一个与formdao相关的实例),所以我不喜欢认为这是同一问题。

好吧,所以我找到了解决方案,尽管我不知道,为什么它的行为。

还记得我说"不必担心同步方法"吗?好吧...事实证明它有几件事是错误的,这进一步延迟了解决方案。

我认为,当网络响应进来时,最重要的错误是更新数据库中的对象的方法。我曾经打电话

@Update
void update(Form form)

在DAO中,由于未知原因,这并不能触发Livedata-Observer。所以我将其更改为

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Form form);

这样做之后,我可以从我的存储库中获得

的formiveata
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,但也许您也有类似的问题。如果是这样,请确保在此处发表评论:)

您必须在所有位置使用相同的数据库实例。

=>使用单身顿

我与您的问题类似 -> livedata在第一次调用之后没有更新其价值

而不是使用livedata使用mutableLivedata,然后将 MutableLiveData<List<Form>>对象传递到列表的新内容的 setValuepostValue

根据我对此的经验,这并不多,显然观察者也将其连接到您首先分配的对象,并且必须对该对象进行所有更改。

最新更新