当前位置: 首页 > 知识库问答 >
问题:

更新数据库时不会更新LiveData列表

隗和裕
2023-03-14

我目前正在重构遗留代码,以使用Android架构组件,并在一种存储库模式中设置一个房间数据库和截取请求。因此,表示层/域层要求存储库获取LiveData对象进行观察,或告诉他与服务器同步,然后删除旧的db条目,并从服务器中重新提取所有当前条目。

我已经写了同步部分的测试,所以我确信,对象被正确地获取并插入到数据库中。但是当写一个测试来观察db表的条目时(并测试对象是否被正确保存,以及在将它们放入db之前需要做的一切),LiveData

在下面的代码片段中,您可以假设,同步方法工作正常,并且异步执行数据库操作。它包含从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的东西,因为这是我第一次使用它们,所以也许我有一些根本性的错误。

非常感谢您的每一点帮助:)

附言:我偶然发现了这篇文章,它讨论了一个类似的问题,但是因为我目前根本没有使用DI,只是使用了一个形式库的实例(它只有一个形式道的实例相关联),所以我不认为这是同一个问题。

共有3个答案

芮叶秋
2023-03-14

我对你的也有类似的问题

不要使用LiveData,而是使用MutableLiveData并传递MutableLiveData

从我的经验来看,这并不多,显然观察者与对象相连,你首先也分配它,并且每一个变化都必须对该对象进行。

毛峻
2023-03-14

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

=

艾自强
2023-03-14

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

还记得我说过“不要担心同步方法”吗?好结果发现它有几个问题,这进一步推迟了解决方案。

我认为最重要的错误是当网络响应到来时更新数据库中对象的方法。我过去常打电话

@Update
void update(Form form)

由于未知的原因,它没有触发实时数据观察者。所以我把它改为

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(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个表单,然后每个表单都会被更改一次(第一次我加载一个包含所有表单的列表,其中包含减少的数据,第二次我再次从服务器上加载每个项目,用更多数据替换数据库中的旧值和新值)。

我不知道这是否会帮助你@joao86,但也许你也有类似的问题。如果是这样,请确保在这里发表评论:)

 类似资料:
  • UserViewModel: 用户存储库:

  • 在我的片段中,我观察到db问卷列表字段: 在我的片段中,我有几个按钮,根据哪个按钮被按下,我在viewModel上调用方法,将设置为标签的字符串传递给按钮。 我的视图模式: 存储库方法: Dao方法: 当我按下按钮时,viewModel方法被调用,并带有参数,该参数应该用于通过搜索房间数据库来更新LiveData,但没有任何内容会被无缘无故地更新。数据库不是空的,所以没有理由在主片段中返回null

  • 我试图在下面的代码中找出,为什么当我用新数据填充数据库时,Room的LiveData observable没有给我新的班次。 这是放在我的activity的onCreate方法上的: 这是populateAdapter方法: 我还有以下填充数据库的代码(我使用RxJava在IO线程上完成这项工作,因为Room需要在主线程之外调用它的代码): 当我开始观察ShiftsViewModel之后调用per

  • 因此,我使用LiveData和ViewModel设置获取和插入数据的功能,并使用Room数据库保存数据。 将数据插入数据库后,我的RecyclerView不会更新数据。 RecyclerAdapterTransaksi.kt 使用RecyclerView显示数据库数据的片段 Pemasukkanframent。kt 使用LiveData的ViewModel类 TransaksiViewModel.

  • 我想知道ehcache是否有办法检测数据库更新/插入(spring/java,hibernate web应用程序),并使用数据库中的当前(最新)数据刷新其缓存。如果没有,检测数据库更新的最佳方法是什么,以保持与缓存和数据库之间的数据同步?

  • 问题内容: 我正在使用()查找PostLikes表中的(PostId,UserId),如果找到该行,则用于生成delete指令并删除基础行,如果未找到该行,则用于生成insert命令并使用将该行插入表中。但是该行未插入数据库中的表中。这是我到目前为止所做的 和表 PostLikes(LikeId,PostId,UserId) 问题答案: 有几个问题: 您正在寻找重复使用相同的命令,这两个检测行是否