我想使用RxJava实现类似AsyncTask的进度条功能

11

我想在Android中用RxJava替换我的AsyncTask。 我目前的AsyncTask是这样的:

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();
    }
}

这是我的RxJava替代方案:

    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;
}

我的活动:

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());
   }
}

我该如何模仿AsyncTask中的onPreExecute()方法,在其中启动progressDialog?


使用 doOnNext() 方法。 - Tuby
@Tuby 你是怎么做到的? - Kristy Welsh
查看这个类 https://github.com/TwistedEquations/android-rxmvp-tutorial/blob/master/app/src/main/java/com/twistedequations/rxmvp/sample/activities/home/mvp/HomePresenter.java,它使用 doOnNext 将 showLoading 设置为 true,从而启用进度条。你可以在这个方法中调用 ringProgressDialog.show()。 - Tuby
4个回答

5
这是我如何做到的:
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
})

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();
           }
       })
    

1
我在doOnSubscribe()中显示progressBar,在doOnError()subscribe()中隐藏。请参考this链接获取更多详细信息。

0

无耻的宣传

我为此创建了RxLoading库,它可以做到这一点以及更多,

你只需要像这样做:

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

它由两个类组成,一个自定义视图(loadingLayout)和RxLoading,它是一个转换器,将它们粘合在一起,您可以选择同时使用它们或其中任何一个。 如果您想要带有简单进度条的RxLoading,您只需要实现一个接口就可以了。

您可以在GitHub页面上查看更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接