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

更新数据库时不触发Room-LiveData观察器

秦昂然
2023-03-14

我试图在下面的代码中找出,为什么当我用新数据填充数据库时,Room的LiveData observable没有给我新的班次。

这是放在我的activity的onCreate方法上的:

shiftsViewModel = ViewModelProviders.of(this).get(ShiftsViewModel.class);
shiftsViewModel
            .getShifts()
            .observe(this, this::populateAdapter);

这是populateAdapter方法:

private void populateAdapter(@NonNull final List<Shift> shifts){

    recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(shifts));
}

我还有以下填充数据库的代码(我使用RxJava在IO线程上完成这项工作,因为Room需要在主线程之外调用它的代码):

@Override
public Observable<List<Shift>> persistShifts(@NonNull final List<Shift> shifts){

    return Observable.fromCallable(() -> {

        appDatabase.getShiftDao().insertAll(shifts);
        return shifts;
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread());
}

当我开始观察ShiftsViewModel之后调用persistShifts时,我遇到的问题就出现了。我希望我的观察者(LiveData)会被所有新添加的移位触发。结果是触发了观察者,但返回的是一个空的移位列表。使其“工作”的唯一方法是离开activity(因此破坏当前的ViewModel)并再次进入。这一次,ViewModel的LiveData给了我以前坚持的所有转移,正如预期的那样。

以下是代码的其余部分:

@Entity
public class Shift{

   @PrimaryKey
   private long id;

   private String start;
   private String end;
   private String startLatitude;
   private String startLongitude;
   private String endLatitude;
   private String endLongitude;
   private String image;
   ...

道:

@Dao
public interface ShiftDAO {

   @Query("SELECT * FROM shift")
   LiveData<List<Shift>> getAll();

   @Query("SELECT * FROM shift WHERE id = :id")
   LiveData<Shift> getShiftById(long id);

   @Insert(onConflict = OnConflictStrategy.REPLACE)
   void insertAll(List<Shift> shifts);
}

ViewModel:

public class ShiftsViewModel extends AndroidViewModel{

   private final ISQLDatabase sqlDatabase;

   private MutableLiveData<Shift> currentShift;
   private LiveData<List<Shift>> shifts;
   private boolean firstTimeCreated;


   public ShiftsViewModel(final Application application){

      super(application);

      this.sqlDatabase = ((ThisApplication) application).getSQLDatabase();
      this.firstTimeCreated = true;
   }

   public MutableLiveData<Shift> getCurrentlySelectedShift(){

      if(currentShift == null){
         currentShift = new MutableLiveData<>();
      }

      return currentShift;
   }

   public LiveData<List<Shift>> getShifts() {

      if(shifts == null){
         shifts = sqlDatabase.queryAllShifts();
      }

     return shifts;
   }

   public void setCurrentlySelectedShift(final Shift shift){

      currentShift = getCurrentlySelectedShift();

      currentShift.setValue(shift);
   }

   public boolean isFirstTimeCreated(){
      return firstTimeCreated;
   }

   public void alreadyUsed(){
      firstTimeCreated = false;
   }
}

为什么我不能直接在observe()回调中得到我坚持的轮班列表?

共有1个答案

扶杜吟
2023-03-14

我在使用Dagger2时遇到了一个类似的问题,这是由Dao的不同实例引起的,一个用于更新/插入数据,另一个用于提供用于观察的LiveData的不同实例。一旦我将Dagger配置为管理Dao的单个实例,那么我就可以在后台插入数据(在我的例子中是在服务中),同时在activity中观察LiveData-并且将调用onChange()回调。

它归结为Dao的实例必须是插入/更新数据和提供LiveData以供观察的同一个实例。

 类似资料:
  • 我有一个视图模型,从场景中接收流作为livedata 在活动中,我们订阅了这个livedata,一些逻辑发生并使用了activityResult 当我们返回时,我们会用最后一个状态触发一个观察者,并再次执行之前的导航逻辑 如何忽略返回时具有相同值的观察者触发器?

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

  • 试图让LiveData与Room一起工作: 因为我观察到tdao.getall(),所以我希望在我的活动中,当同步完成时,它会刷新日历。现在,您必须重新加载该活动,以获取在执行同步后放入数据库的数据。我对Room和LiveData很陌生。有什么想法吗?希望我没有拿出太多的代码,这是从一个相当大的应用程序到目前为止。

  • 我目前正在重构遗留代码,以使用Android架构组件,并在一种存储库模式中设置一个房间数据库和截取请求。因此,表示层/域层要求存储库获取LiveData对象进行观察,或告诉他与服务器同步,然后删除旧的db条目,并从服务器中重新提取所有当前条目。 我已经写了同步部分的测试,所以我确信,对象被正确地获取并插入到数据库中。但是当写一个测试来观察db表的条目时(并测试对象是否被正确保存,以及在将它们放入d

  • UserViewModel: 用户存储库:

  • 此外,为什么Viewmodel不能观察到它自己的LiveData的变化?