2017-09-08 7 views
2

J'essaie de filtrer une liste qui pourrait être vide ou non (ou l'élément ne figure pas dans la liste). inboxData est rempli par un autre observable:Filtrage de la liste vide par RxJava et utilisation de firstOrDefault

private BehaviorSubject<InboxResponse> inboxData = BehaviorSubject.create(); 

public Observable<Item> getInboxItem(String id) { 
    return inboxData 
     .flatMap(response -> Observable.from(response.getData())) 
     .filter(item -> item.getId().equals(id)) 
     .firstOrDefault(null); 
} 

Dans ce cas, si response.getData() est vide FirstOrDefault fonctionne jamais. Mais pourquoi? Il indique clairement qu'il vous redonne la valeur par défaut si l'observable précédent n'émet rien.

+0

@ La réponse de Kiskae est correcte. Notez également qu'une fois que vous appelez 'onCompleted' sur un' BehaviorSubject', tous les observateurs suivants recevront uniquement 'onCompleted', jamais de données. Je ne suis pas sûr qu'un 'Sujet 'soit ce que vous cherchez ici. – theFunkyEngineer

Répondre

3

firstOrDefault émet la valeur par défaut si le flux complète sans éléments étant passé par l'observable. Pour que votre flux se termine, le BehaviorSubject doit signaler l'achèvement. Comme il n'y a aucune indication que cela arrive, il ne réalisera jamais qu'il doit envoyer la valeur par défaut.

La solution consiste à déplacer le filter et firstOrDefault à l'intérieur de la flatMap si la fin de la liste fournie par getData finit par remplir le flux interne. Notez que si vous utilisez RxJava2 comme vos balises le suggèrent, null ne peut jamais être un élément du flux, donc le transmettre par défaut provoquerait une exception.

+0

Merci, figuré quelque chose sur onComplete! – breakline

0
public Observable<Item> getInboxItem(String id) { 
    return inboxData 
     .flatMap(response -> Observable.from(response.getData())) 

À ce stade, response.getData() renvoie null, n'est-ce pas?

 .filter(item -> item.getId().equals(id)) 

Cela signifie que item est null. Donc, item.getId() lance un NullPointerException. Une erreur de ce type est immédiatement transmise au gestionnaire onError de l'abonné. La méthode firstOrDefault ne sera même plus appelée, car le flux est immédiatement terminé.

 .firstOrDefault(null); 
} 
+0

Non, response.getData() est une liste vide s'il n'y a pas de données – breakline

+0

Je pense que c'est quelque chose à propos de behavioursubject qui n'appelle jamais oncomplete de sorte que firstOrDefault ne peut pas appeler la partie par défaut. – breakline