2017-05-15 5 views
0

ich baue meine App auf Android repository by Fernando Cejas und ich habe ein Problem mit dem Abonnement beobachtbar nach dem Aufruf dispose.Subscribe zu beobachtbar nach entsorgen

Wenn ich zu Armaturenbrett kommen, rufen i Methode subscribeOnUserMessages.execute(new Subscriber(), new Params(token)), wobei das Verfahren in UseCase Klasse ist

public void execute(DisposableObserver<T> observer, Params params) { 
    Preconditions.checkNotNull(observer); 
    final Observable<T> observable = this.buildUseCaseObservable(params) 
      .subscribeOn(Schedulers.from(threadExecutor)) 
      .observeOn(postExecutionThread.getScheduler()); 
    addDisposable(observable.subscribeWith(observer)); 
} 

In Kindklasse SubscribeOnUserMessages i rufen Sie einfach Repository wie dieses return messageRepository.subscribeOnUserMessages(params);

In meiner Socket-Implementierung i erstellen wie dieser

return Observable.create(emitter -> { 

     if (!isThereInternetConnection()) { 
      Timber.w("Network connection exception"); 
      emitter.onError(new NetworkConnectionException()); 
      return; 
     } 

     /* 
     * Open socket if not opened 
     */ 
     openSocket(params.getToken()); 



     String channelName = CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid(); 

     if (subscribedChannels.contains(channelName)) { 
      Timber.d("Channel %s is already subscribed", channelName); 
      return; 
     } 


     JSONObject auth; 

     try { 
      auth = createAuthJson(CHANNEL, channelName, params.getToken()); 
     } catch (JSONException e) { 
      Timber.e("Couldn't create auth json"); 
      emitter.onError(e); 
      return; 
     } 

     mSocket.emit(SUBSCRIBE, auth); 
     Timber.d("Emitted subscribe with channel: %s ", CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid()); 
     subscribedChannels.add(CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid()); 
     Timber.d("Subscribing on event: %s\n with user: %s", EVENT_USER_NEW_MESSAGE, params.getAuthenticated().getUuid()); 

     if (mSocket.hasListeners(EVENT_USER_NEW_MESSAGE)) { 
      Timber.v("Socket already has listener on event: %s", EVENT_USER_NEW_MESSAGE); 
      return; 
     } 


     mSocket.on(EVENT_USER_NEW_MESSAGE, args -> { 
      if (args[1] == null) { 
       emitter.onError(new EmptyResponseException()); 
      } 

      Timber.d("Event - %s %s", EVENT_USER_NEW_MESSAGE, args[1].toString()); 

      try { 
       MessageEntity messageEntity = messageEntityJsonMapper.transform(args[1]); 
       emitter.onNext(messageEntity); 
      } catch (JSONException e) { 
       Timber.e(e, "Could not parse message json"); 
       emitter.onError(e); 
      } 
     }); 

    }); 

Symptome a Wenn ich das erste Mal abonniere, läuft alles bis zur Präsentationsschicht. Wenn ich auf den zweiten Bildschirm gehe und zurückkomme, sehe ich nur Logs, die zur Socket-Implementierung kommen, aber nicht durchgehen.

Meine Frage ist: Gibt es eine Methode, um dasselbe Observable wieder zu abonnieren? Ich habe bereits versucht, dieses Observable in meinem Anwendungsfall in Singleton zu speichern und dieses Observable zu abonnieren, hat nicht geholfen.

+0

rufen Sie einfach '.subscribe()' erneut auf das beobachtbare Objekt auf. –

+0

Definieren Sie Ihr Abonnement für das gleiche Observable wieder? Ist es ein heißes Observable oder nicht? Welches Ergebnis möchten Sie sehen, wenn Sie es erneut abonnieren? –

+0

'SocketImpl' ist ein Singleton-Objekt, das für das Abrufen von Nachrichten aus Sockets zuständig ist. –

Antwort

0

Ohne zusätzliche Informationen und Details regrade Socket-Implementierung ist es schwer, das Problem genau zu erkennen, aber, von dem Code, den Sie geschrieben haben, haben Sie keine Verfügungslogik, so während Sie dispose() an die Observable anrufen können Wenn Sie das richtige Lifecycle-Ereignis wählen, bleibt Ihr Socket tatsächlich offen und wird möglicherweise nie richtig getrennt/geschlossen.
Das könnte beim zweiten Mal zu Problemen beim Öffnen und Verbinden mit dem Socket führen, da Sie versuchen könnten, bereits geöffneten Socket wieder zu öffnen und hängt von Ihrem internen Socket impl ab, was ein Problem sein könnte.
(ich kann in dem Kommentar sehen, dass openSocket wenn nicht bereits geöffnet, aber immer noch könnte es ein Problem an anderer Stelle sein, einige Verfahren auf dem Sockel Aufruf mehrmals oder Einstellung Hörer, hängt wiederum von der Buchse impl)

als allgemeinen Richtlinien sollten Sie Dispose-Logik mit emitter.setCancellable()/emitter.setDisposable() hinzufügen, um die Socket-Ressourcen ordnungsgemäß zu entsorgen, wenn Sie sie nicht mehr benötigen. Wenn Sie also subscription erneut anwenden (ob dasselbe Objekt oder nicht), wird die Subscription-Logik erneut aufgerufen, die den Socket erneut öffnet und höre es dir an.

Es ist mir nicht klar, wenn Sie die Steckdose offen halten möchten, wenn Sie auf einen anderen Bildschirm wechseln (ich halte das nicht für eine gute Übung, da Sie diese Ressource offen halten und nie wieder zurückfinden der Bildschirm wieder, um es zu verwenden), aber wenn das der Fall ist, wie @Phoenix Wang erwähnte, können Sie publish kind Operatoren Multicast Observable verwenden, so dass jeder neue Subscriber wird nicht versuchen, den Socket (dh Aufruf der Abonnementlogik) wieder zu öffnen, aber Benachrichtigungen über Nachrichten erhalten, die im bereits geöffneten Socket ausgeführt werden.

+0

Ich habe gerade 'emitter.setCancellable()' und 'emitter.setDisposable()' versucht, aber es würde nicht in diese Methoden fallen. Vielleicht initiiere ich Emitter nicht richtig. –

+0

versuchte auch "observable.doOnDispose()", aber ohne Glück. –

+0

Hat es nicht ausgeführt, wenn Sie das Observable entsorgen? Haben Sie einen zusätzlichen Operator? – yosriz

Verwandte Themen