我想在 RxJava 中使用进度条,就像在 AsyncTask 中一样

Posted

技术标签:

【中文标题】我想在 RxJava 中使用进度条,就像在 AsyncTask 中一样【英文标题】:I want to use a progress bar with RxJava like you can with AsyncTask 【发布时间】:2017-07-08 10:09: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());
   

如何在启动 progressDialog 的 AsyncTask 中模拟 onPreExecute() 方法?

【问题讨论】:

使用 doOnNext() 方法 @Tuby 你是怎么做到的? 查找这个类github.com/TwistedEquations/android-rxmvp-tutorial/blob/master/…,它使用doOnNext设置showLoading为true,开启进度条,你可以在这个方法中调用ringProgressDialog.show()。 【参考方案1】:

我会这样做:

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
)

【讨论】:

【参考方案2】: 在 RxJava 中,您有 do 运算符,它创建 Observable 生命周期事件监听器,在你的情况下你想做一些事情 (更新 UI)在任务开始之前,这意味着你想要 doOnSubscribe 事件。 (旁注对于“冷” Observables 是正确的 在订阅时开始他们的工作 - 就像你的情况一样)只是 请注意之前致电.observeOn(AndroidSchedulers.mainThread())) doOnSubscribe 以便在主线程上得到通知,如 您正在更新用户界面。

而不是同时使用deferjust

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

你可以使用fromCallable:

    Observable.fromCallable(new Callable<Object>() 
       @Override
       public Object call() throws Exception 
           return myTask();
       
   )

【讨论】:

【参考方案3】:

我在doOnSubscribe() 中显示progressBar,隐藏在doOnError()subscribe() 中。

更多详情请参考this链接。

【讨论】:

【参考方案4】:

无耻宣传

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

你可以这样做:

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

它由 2 个类组成,一个自定义视图 (loadingLayout) 和 RxLoading,它是一个 transformer,将它们粘合在一起,您可以选择使用两者或其中之一。 如果你希望 RxLoading 带有一个简单的进度条,你只需要实现一个接口就可以了。

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

【讨论】:

以上是关于我想在 RxJava 中使用进度条,就像在 AsyncTask 中一样的主要内容,如果未能解决你的问题,请参考以下文章

android中的圆形进度条

在科尔多瓦本地通知中显示进度条

Qt 在 Dock 中显示进度条 (macOS)

我想在 j2me 应用程序中添加一个进度条

如何定义地理边界并限制应用程序的使用,就像在 Uber 中一样

如何在 android 中创建进度条而不使用 xml 文件中的进度条小部件?