5

Próbuję dowiedzieć się w poniższym kodzie, dlaczego obserwowane LiveData pokoju nie daje mi nowych zmian, gdy zapełniłem bazę danych nowymi danymi.Pokój - obserwator LiveData nie uruchamia się, gdy baza danych jest aktualizowana

ten jest umieszczany na onCreate metody mojej działalności to:

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

Jest to metoda populateAdapter:

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

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

ja też mam następujący kod, który zapełnia bazę danych (używam RxJava wykonać działa w wątku IO, ponieważ Room wymaga kodu poza głównym wątkiem):

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

Problem, który mam, kiedy wywołuję persistShift po tym, jak zacznę obserwować mój shiftsViewModel. Spodziewałbym się, że mój obserwator (LiveData) zostanie uruchomiony przy wszystkich nowo dodanych zmianach. Okazuje się, że obserwator jest wyzwalany, ale zamiast tego zwracana jest pusta lista zmian. Jedynym sposobem, aby to "działało", jest opuszczenie działania (dlatego zniszczenie bieżącego ViewModel) i ponowne wejście. Tym razem LiveData widokuModel daje mi wszystkie przesunięcia wcześniej utrwalone, zgodnie z oczekiwaniami.

Oto reszta kodu:

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

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

Dlaczego nie otrzymuję listę przesunięć I utrzymują się w return() callback od razu?

+0

Czy możesz pokazać swój kod ViewModel i gdzie/jak dzwonisz getAll()? – Lyla

+0

Niezależnie od tego, pod warunkiem, wyglądają dobrze, ale jak pytano powyżej post ViewModel –

+0

@Lyla ViewModel kod dodany na żądanie. – Tiago

Odpowiedz

20

Miałem podobny problem przy użyciu Dagger 2, który był spowodowany przez różne instancje Dao, jeden do aktualizacji/wstawiania danych, i inne wystąpienie zapewniające LiveData do obserwacji. Po skonfigurowaniu Daggera do zarządzania pojedynczą instancją Dao, mogłem wstawić dane w tle (w moim przypadku w usłudze) podczas obserwacji LiveData w mojej Aktywności - i wywołanie zwrotne onChange().

Sprowadza się do instancji Dao musi być tą samą instancją, która wstawia/aktualizuje dane i dostarcza LiveData do obserwacji.

+0

Tak, aby uzyskać aktualizacje na żywo, musisz upewnić się, że instancja 'Dao' musi być taka sama we wszystkich operacjach. –

+0

Zrobiłem w tym samym problemie i dzięki twojemu anwser dowiedziałem się, że zapomniałem '@ Singleton' na mojej metodzie" RoomDatabase ". Chciałbym dodać, że w moim przypadku mam 2 różne zapytania "Dao" dotyczące tej samej tabeli, z których jedna jest powiązana z klasyczną encją, a druga z klasą otoki z 2 encji osadzonych, aby odtworzyć zapytanie o dołączenie. Chociaż obiekty są różne, 'LiveData' jest poprawnie aktualizowany, więc może to być' RoomDatabase', który musi być singletonem. – devrocca

+0

Emmm kawałek ciasta. –

Powiązane problemy