5

我试图在下面的代码中找到,为什么当我使用新数据填充数据库时,Room的LiveData可观察不会给我新的转换。房间 - 当数据库更新时,LiveData观察器不会触发

这是把我活动的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做因为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)能够在所有新增加的班次中被触发。事实证明,观察者被触发,但是返回的是一个空列表。使其“工作”的唯一方法是如果我离开活动(因此销毁当前的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:

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

为什么我没有得到我的坚持轮班的名单观察()回调直通?

+0

你可以显示你的ViewModel代码和你在哪里/如何调用getAll()? – Lyla

+0

无论提供什么看起来不错,但正如上面提到的问题ViewModel –

+0

@Lyla ViewModel代码根据请求添加。 – Tiago

回答

20

我有一个类似的问题,使用Dagger 2是由于有不同的Dao实例,一个用于更新/插入数据,另一个实例提供LiveData观察。一旦我配置了Dagger来管理Dao的单例实例,那么我可以在我的Activity中观察LiveData的同时在后台插入数据(在我的服务中),并调用onChange()回调函数。

归结为Dao的实例必须是插入/更新数据并提供LiveData进行观察的实例。

+0

是的,要获得实时更新,您必须确保所有操作中的“Dao”实例必须相同。 –

+0

我发生在同样的问题,并感谢您的anwser我发现我忘记'@ Singleton'在我的'RoomDatabase'提供方法。我想补充一点,就我而言,我有两个不同的'Dao'查询同一个表,其中一个与传统实体相关,另一个与包含2个嵌入实体的包装类相关,用于重现连接查询。虽然对象不同,但是“LiveData”被正确更新,所以它可能是'RoomDatabase'必须是单身。 – devrocca

+0

Emmm小菜一碟。 –

相关问题