6

POJO Java ObjectLiveData.getValue() zwraca wartość null z pokoju

public class Section { 

    @ColumnInfo(name="section_id") 
    public int mSectionId; 

    @ColumnInfo(name="section_name") 
    public String mSectionName; 

    public int getSectionId() { 
     return mSectionId; 
    } 

    public void setSectionId(int mSectionId) { 
     this.mSectionId = mSectionId; 
    } 

    public String getSectionName() { 
     return mSectionName; 
    } 

    public void setSectionName(String mSectionName) { 
     this.mSectionName = mSectionName; 
    } 
} 

Moja metoda Zapytanie

@Query("SELECT * FROM section") 
LiveData<List<Section>> getAllSections(); 

Dostęp DB

final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections(); 

W następnym wierszu Mam sprawdzanie sections.getValue() który zawsze daje mi wartość null, chociaż mam dane w bazie danych, a później otrzymuję wartość wMetoda.

sections.observe(this, new Observer<List<Section>>() { 
    @Override 
    public void onChanged(@Nullable List<Section> sections){ 

    } 
}); 

Kiedy jednak pominąć LiveData z zapytania otrzymuję dane zgodnie z oczekiwaniami. Metoda Zapytanie:

@Query("SELECT * FROM section") 
List<Section> getAllSections(); 

Dostęp DB:

final List<Section> sections = mDb.sectionDAO().getAllSections(); 
+1

Ale dlaczego chcesz użyć 'sections.getValue()', a liveata są używane do obserwacji danych. Może być, gdy sprawdzasz w następnej linii, dane nie są ustawiane w trybie liveata, dlatego daje zero. W skrócie, jeśli nie chcesz używać 'LiveData', po prostu użyj go bez' LiveData'. – Moinkhan

+1

Chcę użyć pliku liveata ... jeśli 'sections.getValue()' ma wartość null Muszę wywołać api dla danych i wstawić do bazy danych, która ostatecznie wywoła metodę 'onChange()', skąd otrzymam dane . Ale z powodu tej wartości "null", jeśli i pobieranie danych z bazy danych i api. – CodeCameo

Odpowiedz

4

rozwiązać ten problem dzięki temu podejściu

private MediatorLiveData<List<Section>> mSectionLive = new MediatorLiveData<>(); 
    . 
    . 
    . 

    @Override 
    public LiveData<List<Section>> getAllSections() { 
     final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections(); 

     mSectionLive.addSource(sections, new Observer<List<Section>>() { 
      @Override 
      public void onChanged(@Nullable List<Section> sectionList) { 
       if(sectionList == null || sectionList.isEmpty()) { 
        // Fetch data from API 
       }else{ 
        mSectionLive.removeSource(sections); 
        mSectionLive.setValue(sectionList); 
       } 
      } 
     }); 
     return mSectionLive; 
    } 
+0

Czy możesz mi pomóc? Mam do czynienia z tym samym problemem, gdzie powinienem umieścić ten kod? –

+0

Możesz go znaleźć tutaj ... https://github.com/codecameo/Shobdho – CodeCameo

+0

Na wypadek, gdyby ktokolwiek napotkał ten sam problem, rozwiązanie leży na [MediatorLiveData] (https://developer.android.com /reference/android/arch/lifecycle/MediatorLiveData.html), która jest podklasą, która może obserwować na innych LiveData. –

1

jeśli sections.getValue() jest zerowy Muszę zadzwonić API dla danych i wstawić w do bazy danych

Możesz obsłużyć to na onChange metoda:

sections.observe(this, new Observer<List<Section>>() { 
    @Override 
    public void onChanged(@Nullable List<Section> sections){ 
     if(sections == null || sections.size() == 0) { 
      // No data in your database, call your api for data 
     } else { 
      // One or more items retrieved, no need to call your api for data. 
     } 
    } 
}); 

Powinieneś jednak lepiej umieścić tę logikę inicjalizacji bazy danych/tabeli w klasie repozytoriów. Sprawdź Google's sample. Zobacz klasę DatabaseCreator.

+0

Widziałem już ten przykład, a problem z tym jest, za każdym razem, gdy aplikacja jest uruchamiana 'getDb (kontekst kontekstowy)' jest wywoływana chociaż ma dane powodują, że początkowo 'isDatabaseCreated()' zawsze zwróci false. – CodeCameo

1

I rozwiązał podobny problem następująco

Wewnątrz klasy ViewModel

private LiveData<List<Section>> mSections; 

@Override 
public LiveData<List<Section>> getAllSections() { 

    if (mSections == null) { 
     mSections = mDb.sectionDAO().getAllSections(); 
    } 

    return mSections; 
} 

To wszystko jest wymagane. Nigdy nie zmieniaj instancji LiveData.

2

W następnym wierszu Mam sprawdzanie sections.getValue(), która jest zawsze daje mi zerowy chociaż mam danych w bazie danych, a później otrzymuję wartość w metodzie onChanged().

Myślę, że to normalne zachowanie, ponieważ zapytania zwracające LiveData działają asynchronicznie.

LiveData<List<Section>> getAllSections(); 

Więc colling ten sposób, można uzyskać wynik tutaj

sections.observe(this, new Observer<List<Section>>() { 
@Override 
public void onChanged(@Nullable List<Section> sections){ 

} 
}); 

z dokumentacją:

pokoju nie pozwala dostępu do bazy danych w głównym wątku, chyba że o nazwie allowMainThreadQueries () na konstruktorze, ponieważ może potencjalnie blokować interfejs użytkownika przez dłuższy czas.Zapytania asynchroniczne (zapytania zwracające LiveData lub RxJava Flowable) są wyłączone z tej reguły, ponieważ w razie potrzeby asynchronicznie uruchamiają kwerendę w wątku w tle.