web-dev-qa-db-fra.com

Processus observable sur le fil d'arrière-plan

J'utilise RxAndroid pour les opérations de flux. Dans mon cas d'utilisation réel, je récupère une liste du serveur (en utilisant Retrofit). J'utilise des planificateurs pour effectuer le travail sur un thread d'arrière-plan et obtenir l'émission finale sur le thread Android UI (main)).

Cela fonctionne bien pour l'appel réseau, mais j'ai réalisé que mes opérateurs après l'appel réseau n'utilisent pas le thread d'arrière-plan, mais sont appelés sur le thread principal.

myService.fetchSomeIntegersFromServer()
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .filter(integer -> {
            System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
            return true;
        })
        .subscribe(integer1 -> {});

Comment puis-je m'assurer que toutes les opérations sont exécutées sur un thread d'arrière-plan?

20
WonderCsabo

TL; DR : déplacez observeOn(AndroidSchedulers.mainThread()) sous filter(...).


subscribeOn(...) est utilisé pour désigner sur quel thread le Observable va commencer fonctionner. Les appels suivants à subscribeOn seront ignorés.

Ainsi, si vous deviez écrire ce qui suit, tout serait exécuté sur Schedulers.newThread():

myService.fetchSomeIntegersFromServer()
        .subscribeOn(Schedulers.newThread())
        .filter(integer -> {
            System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
            return true;
        })
        .subscribe(integer1 -> { doSomething(integer1); });

Maintenant, bien sûr, ce n'est pas ce que vous voulez: vous voulez doSomething sur le thread principal.
C'est là que observeOn se met en place. Toutes les actions aprèsobserveOn sont exécutées sur ce planificateur. Par conséquent, dans votre exemple, le filter est exécuté sur le thread principal.

Au lieu de cela, déplacez observeOn vers le bas juste avant subscribe:

myService.fetchSomeIntegersFromServer()
        .subscribeOn(Schedulers.newThread())
        .filter(integer -> {
            System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
            return true;
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(integer1 -> { doSomething(integer1) });

Maintenant, filter se produira sur le 'nouveau thread', et doSomething sur le thread principal.


Pour aller encore plus loin, vous pouvez utiliser observeOn plusieurs fois:

myService.fetchSomeIntegersFromServer()
        .subscribeOn(Schedulers.newThread())
        .observeOn(Schedulers.computation())
        .filter(integer -> {
            System.out.println(Looper.getMainLooper().getThread() == Thread.currentThread());
            return true;
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(integer1 -> { doSomething(integer1) });

Dans ce cas, l'extraction se produira sur un nouveau thread, le filtrage sur un thread de calcul et doSomething sur le thread principal.

Checkout ReactiveX - Opérateur SubscribeOn pour la documentation officielle.

57
nhaarman