How to update UI from Android service using RxJava/RxAndroid
Asked Answered
E

2

18

I have a Bound Service which responsible for downloading files and thus it knows the downloading status/progress. And the UI (Fragment or Activity) has to show/update download progress from the service.

Actually i think the common way is to use BroadcastReciever or a CallBack from Activity. But i heard somewhere about using RxJava (ReactiveX Programming) and mediator class (and Dagger to inject it into both service and activity) which is mentioned below.

So my question is how to handle RxJava with these bunch of stuff? Any Code Samples? Is there another efficient way than using intents?

Resource: More efficient way of updating UI from Service than intents? [ see the first answer update ]

Exit answered 20/11, 2015 at 21:11 Comment(6)
Personally I prefer using Messenger service: developer.android.com/reference/android/os/Messenger.htmlReasoned
I thought I had an example of using Messenger somewhere here, I guess not, but here's a good post detailing its use: #4300791Reasoned
just use "local bound service" pattern, no need for any external libs and it is the fastest solutionNorwich
@pskink, you mean pass a Callback to bound service and use it retrieve new download progress?Exit
yes, this is exactly what i mean, but if you store your downloads in some sqlite db you could use a CursorLoader that queries your custom ContentProvider and the service updates/inserts/deletes your provider, in this case there is no need for any callbacksNorwich
@AmirHoseinKazemNejad It's not exactly what you are looking for but maybe this article will inspire you donnfelker.com/rxjava-with-aidl-servicesSwoon
P
15

Required of RxJava/RxAndroid

1) OBSERVABLES 2) OBSERVERS 3) SUBSCRIBE

Plan where you need to place your 1, 2, 3,

OBSERVABLES go where the data is created, so In your case SERVICE

OBSERVERS go where the data needs to be consumed(or displayed), so that's your ACTIVITY

SUBSCRIBE goes anywhere where you have access to OBSERVABLE & OBSERVER, so lets use ACVITITY for that

Procedure and Code:

Firstly, Prepare your OBSERVABLE in service like this

class MyService extends Service {
    static PublishSubject<String> data = PublishSubject.create();

   @Override
   public void onStarCommand(Intent intent,int i, int j){
        # DO THIS ANYWHER WHERE YOU GENERATE DATA 
        data.onNext("Hello");
   }

   public static Observable<String> getObservable(){
      return data;
   }
}

Secondly, Prepare your OBSERVER(and OBSERVABLE) in Activity's onCreate

Observable<String> observable = MyService.getObservable();
Observer<String> observer = new Observer<String>() {
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted: ");
        }

        @Override
        public void onError(Throwable e) {
            Log.e(TAG, "onError: ",e);
        }

        @Override
        public void onNext(String text) {
            Log.d(TAG, "DATA reveived here: "+text);
        }
    };

Lastly Link both OBSERVER and OBSERVABLE in Activity, else Observable will not respond, use this again in onCreate

observable.subscribe(observer);

DONE, Now when even the data is triggered from Service using onNext(), the data arrives in Activity

Padus answered 16/4, 2018 at 20:24 Comment(3)
And how to do this without static fields?Reprehension
public void onCompleted() should be public void onComplete(). Also missing onSubscribe() method.Beals
app crashes when activity/fragment is destroyed or not active.. how to handle this?Hbeam
F
4

The Binder subclass you use when something binds to your Service can expose a method that returns an Observable which emits progress data.

The caveat with this approach is that you have two resources which you need to release when the Activity instance is no longer valid: the service connection and the observable subscription.

Fieldfare answered 26/10, 2016 at 10:21 Comment(5)
can you explain your comment , or give some example ?Indigent
Bad answer. Observable is not serialized object, so not sure if it will work, especially if service is designed for cross-process interaction. Wont work.Burtonburty
Cross-process interaction is outside the scope of this question. Otherwise, it's basically the same as exposing your Service instance via the Binder, and the Service is also not serializable.Fieldfare
@LeonardoAcevedo, haven't tested, but shouldn't workBurtonburty
@Burtonburty for a local bound service there should be no need for serialization, do you think that would work on that case?Cacomistle

© 2022 - 2024 — McMap. All rights reserved.