2017-09-06 15 views
3

Je suis très novice dans la programmation Rx et j'essayais de la mettre dans un projet. Ce que je veux est que j'ai un objet de GamesInfoList comme indiqué ci-dessous:RxJava2: Filtrer une liste <Object> dans un Observable

@AutoValue 
public abstract class GameInfoList { 
    public static TypeAdapter<GameInfoList> typeAdapter(Gson gson) { 
     return new AutoValue_GameInfoList.GsonTypeAdapter(gson); 
    } 

    public static Builder builder() { 
     return new AutoValue_GameInfoList.Builder(); 
    } 

    public abstract long id(); 

    @Nullable 
    public abstract String date_added(); 

    @Nullable 
    public abstract String date_last_updated(); 

    @Nullable 
    public abstract GameImages image(); 

    @Nullable 
    public abstract String name(); 

    @Nullable 
    public abstract List<GamePlatformInfo> platforms(); 

    @AutoValue.Builder 
    public abstract static class Builder { 

     public abstract Builder id(long id); 

     public abstract Builder date_added(String date_added); 

     public abstract Builder date_last_updated(String date_last_updated); 

     public abstract Builder image(GameImages image); 

     public abstract Builder name(String name); 

     public abstract Builder platforms(List<GamePlatformInfo> platforms); 

     public abstract GameInfoList build(); 
    } 
} 

Maintenant, je veux charger mes jeux par date et nom et j'ai écrit une méthode pour que pour accéder à cet objet ci-dessus en elle.

public void loadGamesByDateAndName(String date, String name) { 
    Timber.d("Load games by date: " + date + " and name: " + name); 
    remoteDataHelper 
      .getGamesListByDate(date) 
      .flatMapObservable(Observable::fromIterable) 
      .filter(game -> game.platforms() != null) 
      .filter(game -> game.platforms().name().contains(name)) 
      .toList() 
      .subscribe(getObserverFiltered(name, false)); 
} 

Ici, je filtration (en utilisant l'opérateur de filtre()), les plates-formes objet sur la base du nom entré dans ce procédé. La méthode ci-dessus me montre une erreur parce que la plate-forme est de type Liste. Comment puis-je filtrer dans la liste pour faire correspondre le nom et l'affichage dans mon application Android? Quels changements doivent être apportés à la méthode ci-dessus pour charger les données par date et nom?

Répondre

3

La méthode la plus simple consiste à parcourir le second opérateur filter.

public void loadGamesByDateAndName(String date, String name) { 
    Timber.d("Load games by date: " + date + " and name: " + name); 
    remoteDataHelper 
      .getGamesListByDate(date) 
      .flatMapObservable(Observable::fromIterable) 
      .filter(game -> game.platforms() != null) 
      .filter(game -> { for(GamePlatformInfo platform : game.platforms()){ 
            if(platform.name().contains(name)) { 
             return true; 
            } 
           } 
           return false; 
        } 
      ) 
      .toList() 
      .subscribe(getObserverFiltered(name, false)); 
} 
+0

Je suppose que cela devrait fonctionner très bien et, par conséquent, je vais accepter cette réponse. Je vais le tester une fois. Merci beaucoup!!! :-) –

+1

Parfois, la solution la plus simple est la meilleure. Probablement, vous pouvez construire quelque chose de plus RXy et intelligent, mais à la fin, il sera juste plus difficile à comprendre pour la prochaine personne qui le lit. Ou pour vous un mois plus tard;) – theFunkyEngineer

+0

Ouais je suppose. Les opérateurs sont si difficiles à garder à l'esprit. Besoin de les utiliser dans beaucoup de projets que je présume. –

-1

Eh bien, vous devez remplacer la méthode equals() dans GamePlatformInfo classe.

Je suppose que vous avez définition de classe suivante de GamePlatformInfo classe:

class GamePlatformInfo{ 
    String name; 
    ... 
    ... 

    public GamePlatformInfo(String name){ 
     this.name = name; 
     ... 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (o == this) return true; 
     if (!(o instanceof GamePlatformInfo)) return false; 
     final GamePlatformInfo other = (GamePlatformInfo)o; 
     return name.equals(other.name); 
    } 

    @Override 
    public int hashCode() { 
     int result = 17; 
     result = 31 * result + name.hashCode(); 
     return result; 
    } 
} 

Ensuite il vous suffit de d'utiliser l'opérateur pour rechercher dans cette liste. Vérifiez les points suivants extrait modifié:

public void loadGamesByDateAndName(String date, String name) { 
    Timber.d("Load games by date: " + date + " and name: " + name); 
    remoteDataHelper 
      .getGamesListByDate(date) 
      .flatMapObservable(Observable::fromIterable) 
      .filter(game -> game.platforms() != null) 
      .filter(game -> game.platforms().contains(new GamePlatformInfo(name))) // This is all you need to do to search through the list. 
      .toList() 
      .subscribe(getObserverFiltered(name, false)); 
} 

Sous le capot: Si vous créez une liste d'une classe qui remplace la méthode equals() puis méthode utilise list.contains() donnée égale définition pour comparer les éléments de la liste.

J'espère que ça aide.

+0

Ceci est incorrect. 'List # contains' fonctionne en utilisant la méthode' equals' de la classe, pas 'compareTo', comme documenté [ici] (https://docs.oracle.com/javase/7/docs/api/java/util/List.html #contains (java.lang.Object)). Et outrepassant les «égaux» de votre classe juste pour ce cas d'utilisation est une très mauvaise idée, car cela causera probablement des problèmes dans d'autres endroits. – theFunkyEngineer

+0

@theFunkyEngineer vous avez raison. 'Comparable' est utilisé pour le tri, j'ai corrigé la réponse. Overriding égaux n'est pas une mauvaise idée. Si vous l'appliquez correctement, vous ne casserez rien. Jetez un oeil à l'implémentation 'equals()'. Même il vient dans les meilleures pratiques lors de l'utilisation des listes, pas itérativement aveuglément si la liste en utilisant pour la boucle. – chandil03

+0

@theFunkyEngineer dans RxJava, ce n'est pas la meilleure pratique pour casser la chaîne 'Observable' que vous avez fait pour rechercher dans la liste. Je ne dis pas que vous avez tort, mais c'est ainsi que le code idiomatique devrait être écrit. sans offense, merci de votre compréhension. – chandil03