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小菜一碟。 –

相關問題