2017-12-20 18 views
2

So habe ich zwei Modelle (Tabellen), WordGroups und Words, und die Beziehung zwischen ihnen ist eins zu viele. Also meine Modelle und Dao wie folgt aussehen:Android Room: Umgang mit Beziehungen mit LiveData

@Entity 
public class WordGroup { 

    @PrimaryKey 
    private int id; 

    @Ignore 
    private List<Word> words; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public List<Word> getWords() { 
     return words; 
    } 

    public void setWords(List<Word> words) { 
     this.words = words; 
    } 
} 

@Entity 
public class Word { 

    @PrimaryKey 
    private int id; 

    @ForeignKey(entity = WordGroup.class, parentColumns = "id", childColumns = "wordGroupId") 
    private int wordGroupId; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public int getWordGroupId() { 
     return wordGroupId; 
    } 

    public void setWordGroupId(int wordGroupId) { 
     this.wordGroupId = wordGroupId; 
    } 
} 

und

@Dao 
public interface Dao { 

    @Query("select * from WordGroup where id = :id") 
    LiveData<WordGroup> selectWordGroupById(int id); 

    @Query("select * from WordGroup") 
    LiveData<List<WordGroup>> selectAllWordGroups(); 

    @Query("select * from Word where wordGroupId = :wordGroupId") 
    LiveData<List<Word>> selectWordsByWordGroupId(int wordGroupId); 
} 

jetzt habe ich eine Methode, die eine WordGroup und setzt auch seine Word s mit Transformations wählt: Jetzt

public LiveData<WordGroup> getWordGroupWithWords(int id) { 
    LiveData<WordGroup> wordGroupLiveData = dao.selectWordGroupById(id); 

    LiveData<WordGroup> wordGroupWithWordsLiveData = Transformations.switchMap(wordGroupLiveData, inputWordGroup -> { 
     LiveData<List<Word>> wordsLiveData = dao.selectWordsByWordGroupId(inputWordGroup.getId()); 

     LiveData<WordGroup> outputWordGroupsLiveData = Transformations.map(wordsLiveData, inputWords -> { 
      inputWordGroup.setWords(inputWords); 
      return inputWordGroup; 
     }); 

     return outputWordGroupsLiveData; 
    }); 

    return wordGroupWithWordsLiveData; 
} 

Ich möchte eine Methode schreiben, die alle WordGroup s auswählt, die auch ihresetzts für jede WordGroup. die Signatur der Methode sollte so etwas wie sein:

public LiveData<List<WordGroup>> getAllWordGroupsWithWords(); 

Antwort

0

Nun habe ich versucht, ein bisschen mehr und ich kam mit dieser Lösung mit Hilfe von MediatorLiveData up:

public LiveData<List<WordGroup>> getAllWordGroupsWithWords() { 
    LiveData<List<WordGroup>> wordGroupsLiveData = dao.selectAllWordGroups(); 
    LiveData<List<WordGroup>> outputWordGroups = Transformations.switchMap(wordGroupsLiveData, inputWordGroups -> { 
     MediatorLiveData<List<WordGroup>> wordGroupsMediatorLiveData = new MediatorLiveData<>(); 
     for (WordGroup wordGroup : inputWordGroups) { 
      wordGroupsMediatorLiveData.addSource(dao.selectWordsByWordGroupId(wordGroup.getId()), words -> { 
       wordGroup.setWords(words); 
       wordGroupsMediatorLiveData.postValue(inputWordGroups); 
      }); 
     } 

     return wordGroupsMediatorLiveData; 
    }); 

    return outputWordGroups; 
} 

jetzt ist es genau die Art und Weise Ich wollte, aber es gibt einige große Probleme.

  • Zuerst wird es dem Betrachter oft aufrufen, wenn Sie die Methode verwenden setValue auf Ihrem MediatorLiveData, ich konnte es dem Betrachter durch weniger oft machen rufen mit postValue

  • Zweitens, auch wenn Sie nur ein Wort ändern , wird es den Beobachter für jede wordGroup wieder aufrufen!

Natürlich ist es nicht die am besten optimierte Lösung, aber es funktioniert. Ich bin wirklich offen für Vorschläge und Verbesserungen.

+0

überprüfen Sie diesen Artikel https://medium.com/@rezabigdeli6/android-room-handling-relations-using-livedata-2d892e40bd53 –

Verwandte Themen