I want to use a progress bar with RxJava like you can with AsyncTask
Asked Answered
I

4

11

I want to replace my AsyncTask with RxJava in android. My current AsyncTask goes like this:

public class ProgressBarAsyncTask extends AsyncTask<Void,Void,Void> { 

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        ringProgressDialog = ProgressDialog.show(context,"MyProgressBarTitle","Working please wait",true, false);                  
    }

    @Override
    protected Void doInBackground(Void... void) { 
       //do work
       myTask();
       return null;
    }

    @Override
    protected void onPostExecute(Void void) {
        super.onPostExecute();
        ringProgressDialog.dismiss();
    }
}

Here's my RxJava replacement:

    public static Observable<Void> getObservable(final Context context,final String... params) {

       return Observable.defer(new Func0<Observable<Void>>() {
          @Override
          public Observable<Void> call() {
             return Observable.just(myTask());
          }
       });

   }

    public static Subscriber<Void> getSubscriber() {
    Subscriber<Void> subscriber = new Subscriber<Void>() {
        @Override
        public void onCompleted() {
           ringProgressDialog.dismiss();

        }

        @Override
        public void onError(Throwable e) {
            Log.d(TAG,e.toString());

        }

        @Override
        public void onNext(Void aVoid) {
             manipulateData();

        }
    };
    return subscriber;
}

My Activity:

public class MainActivity extends Activity { 
   private ProgressDialog ringProgressDialog;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      GetNumberObservable.Observable()
                       .subscribeOn(Schedulers.io())
                       .observeOn(AndroidSchedulers.mainThread()))
                       .subscribe(getSubscriber());
   }
}

How do I mimic the onPreExecute() method in the AsyncTask where I kick off the progressDialog?

Inspirational answered 19/2, 2017 at 0:47 Comment(3)
Use doOnNext() methodArmure
@Armure How do you do that?Inspirational
lookup this class github.com/TwistedEquations/android-rxmvp-tutorial/blob/master/…, it uses doOnNext to set showLoading to true, which enables progress bar, you could call ringProgressDialog.show() in this method.Armure
S
4
  • In RxJava you have the do operators, that creates Observable lifecycle events listeners, in your case you want to do something (update the UI) before the task started, which mean you want the doOnSubscribe event. (side note it is true with 'cold' Observables that started thier work when subscrbied to - like your case) Just beware to call .observeOn(AndroidSchedulers.mainThread())) before the doOnSubscribe in order to get notified on the mainThread, as you're updating the UI.
  • Instead of using both defer and just

    return Observable.defer(new Func0<Observable<Void>>() {
         @Override
         public Observable<Void> call() {
            return Observable.just(myTask());
         }
      });  
    

    you can use fromCallable:

        Observable.fromCallable(new Callable<Object>() {
           @Override
           public Object call() throws Exception {
               return myTask();
           }
       })
    
Shane answered 19/2, 2017 at 5:58 Comment(0)
E
5

Here is how I would do it:

public final class ProgressOrResult<T> {
    final int progress;
    final T result;
    public ProgressOrResult(int progress, T result) {
        this.progress = progress;
        this.result = result;
    }
}

ProgressDialog ringProgressDialog = ProgressDialog.show(
    context, "MyProgressBarTitle", "Working please wait", true, false);                  


Observable.fromEmitter((Emitter<ProgressOrResult> emitter) -> {
    // generate "progress"
    int sum = 0;
    for (int i = 1; i <= 100; i++) {
        sum += i;
        emitter.onNext(new ProgressOrResult(i, null));
        Thread.sleep(1);
    }
    // generate "result"
    emitter.onNext(new ProgressOrResult(100, sum));
    emitter.onComplete();

}, BackpressureMode.BUFFER)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
    if (pr.result == null) {
        ringProgressDialog.setProgress(pr.progress);
    } else {
        ringProgressDialog.dismiss();        

        // process the result here
    }
}, error -> {
    // handle error here
})
Eraste answered 19/2, 2017 at 10:16 Comment(0)
S
4
  • In RxJava you have the do operators, that creates Observable lifecycle events listeners, in your case you want to do something (update the UI) before the task started, which mean you want the doOnSubscribe event. (side note it is true with 'cold' Observables that started thier work when subscrbied to - like your case) Just beware to call .observeOn(AndroidSchedulers.mainThread())) before the doOnSubscribe in order to get notified on the mainThread, as you're updating the UI.
  • Instead of using both defer and just

    return Observable.defer(new Func0<Observable<Void>>() {
         @Override
         public Observable<Void> call() {
            return Observable.just(myTask());
         }
      });  
    

    you can use fromCallable:

        Observable.fromCallable(new Callable<Object>() {
           @Override
           public Object call() throws Exception {
               return myTask();
           }
       })
    
Shane answered 19/2, 2017 at 5:58 Comment(0)
U
1

I am showing progressBar indoOnSubscribe() , hiding in doOnError() and in subscribe().

Please refer to this link for more details.

Unhallowed answered 22/8, 2018 at 11:56 Comment(0)
H
0

Shameless Promotion

I've created RxLoading library for that, it can do this and much more,

you can just do something like this:

networkCall().compose(RxLoading.<>create(loadingLayout)).subscribe(...);

it consists out of 2 classes, a custom view (loadingLayout) and RxLoading which is a transformer that glue it all together, you can choose to work with both or either of them. if you want RxLoading with a simple progress bar you just need to implement an interface and you are done.

you can check more on the GitHub page.

Hema answered 4/3, 2018 at 8:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.