Room - LiveData 观察者不会在数据库更新时触发 [英] Room - LiveData observer does not trigger when database is updated

查看:76
本文介绍了Room - LiveData 观察者不会在数据库更新时触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在下面的代码中找出为什么在我用新数据填充数据库后 Room 的 LiveData observable 没有给我新的变化.

I am trying to find out in the code below, why is it that Room's LiveData observable does not give me new shifts once I populate the database with new data.

这是放在我的活动的 onCreate 方法上:

This is put on my activity's onCreate method:

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

这是 populateAdapter 方法:

This is the populateAdapter method:

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

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

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

I also have the following code that populates the database (I use RxJava to do the work on an IO thread since Room needs its code to be called outside the main thread):

@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).结果发现观察者被触发了,但返回的是一个空的班次列表.让它工作"的唯一方法是我离开活动(因此破坏当前的ViewModel)并再次进入.这次 viewModel 的 LiveData 给了我之前坚持的所有变化,正如预期的那样.

The problem I have occurs when I call persistShifts after I start observing my shiftsViewModel. I would expect that my observer (LiveData) would be triggered with all the newly added shifts. It turns out the observer is triggered, but an empty list of shifts is returned instead. The only way to make it "work" is if I leave the activity (therefore destroying the current ViewModel) and enter again. This time the viewModel's LiveData gives me all the shifts previously persisted, as expected.

其余代码如下:

@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:

@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);
}

视图模型:

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() 回调中坚持的班次列表?

Why am I not getting the list of shifts I persist in the observe() callback straightaway?

推荐答案

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

I had a similar problem using Dagger 2 that was caused by having different instances of the Dao, one for updating/inserting data, and a different instance providing the LiveData for observing. Once I configured Dagger to manage a singleton instance of the Dao, then I could insert data in the background (in my case in a Service) while observing LiveData in my Activity - and the onChange() callback would be called.

归结起来,Dao 的实例必须是插入/更新数据并提供 LiveData 以供观察的同一个实例.

It comes down to the instance of the Dao must be the same instance that is inserting/updating data and providing LiveData for observation.

这篇关于Room - LiveData 观察者不会在数据库更新时触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆