RxJava2就像Android中的AsyncTask一样

时间:2017-04-21 04:18:46

标签: android rx-java reactive-programming rx-java2

您好我刚开始使用RxJava2学习反应式编程。 如何创建在后台线程中运行的任务,然后使用RxJava2在主线程上完成。

Android中的示例我们使用AsyncTask就像下面的示例

private class MyTask extends AsyncTask<String, Integer, Boolean>
{
    @Override
    protected Boolean doInBackground(String... paths)
    {
        for (int index = 0; index < paths.length; index++)
        {
            boolean result = copyFileToExternal(paths[index]);

            if (result == true)
            {
                // update UI
                publishProgress(index);
            }
            else
            {
                // stop the background process
                return false;
            }
        }

        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values)
    {
        super.onProgressUpdate(values);
        int count = values[0];
        // this will update my textview to show the number of files copied
        myTextView.setText("Total files: " + count);
    }

    @Override
    protected void onPostExecute(Boolean result)
    {
        super.onPostExecute(result);
        if (result)
        {
            // display a success dialog
            ShowSuccessAlertDialog();
        }
        else
        {
            // display a fail dialog
            ShowFailAlertDialog();
        }
    }
}

对于这个例子,我想传入一个Strings的Array / ArrayList,它用于在 后台线程 中执行一些方法。然后,每个成功结果都将更新我的 TextView(UI线程)。如果其中一个进程失败,我希望它直接停止。最后,我想在流程完成后更新我的视图

我只能设法做到这一点

Observable.just(paths).subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<ArrayList<String>>()
            {
                private boolean result;

                @Override
                public void onSubscribe(Disposable d)
                {
                }

                @Override
                public void onNext(ArrayList<String> paths)
                {
                    for (int index = 0; index < paths.size(); index++)
                    {
                        result = copyFileToExternal(paths[index]);

                        if (result == true)
                        {
                            // cant update UI because is in background thread
                            myTextView.setText("Total files: " + index);
                        }
                        else
                        {
                            // end the loop
                            break;
                        }
                    }
                }

                @Override
                public void onError(Throwable e)
                {
                }

                @Override
                public void onComplete()
                {
                    if (result)
                    {
                        // cant display because it is still in background thread
                        ShowSuccessAlertDialog();
                    }
                    else
                    {
                        // cant display because it is still in background thread
                        ShowFailAlertDialog();
                    }
                }
            });

我查看了一些教程,但似乎无法找到答案。

提前感谢您的帮助

2 个答案:

答案 0 :(得分:4)

我会做这样的事情:

Observable.fromArray(getPaths())
    .map(path -> copyFileToExternal(path))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(aInteger -> Log.i("test", "update UI"),
               throwable -> ShowFailAlertDialog),
               () -> ShowSuccessAlertDialog());

一个好主意通常是拥有一个&#34;处理程序&#34;用于控制对观察者的订阅。因此,当您需要停止后台任务时(例如,因为用户离开了Activity),您可以使用它。为此,您可以使用subscribeWith而不是subscribe作为输入ResourceObserver:这样您就可以得到Disposable

Disposable subscription = Observable.fromArray(getPaths())
    .map(path -> copyFileToExternal(path))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeWith(new ResourceObserver<Integer>() {
         @Override
         public void onNext(@NonNull Integer index) {
             Log.i("test", "update UI");
         }
         @Override
         public void onError(@NonNull Throwable e) {
             ShowFailAlertDialog();
         }
         @Override
         public void onComplete() {
             ShowSuccessAlertDialog();
         }
   });

当您需要停止任务时,您可以致电:

subscription.dispose();

答案 1 :(得分:1)

我是新手,但我有一个有效的例子......

//Observable
Observable.just("input_parameter")
            .subscribeOn(Schedulers.io())//creation of secondary thread
            .map(new Function<String, String>() {//<input obj,return obj>
                @Override
                public String apply(String cad){//input obj
                    Log.d(TAG,"thread :"+Thread.currentThread().getName());
                    //runs in a secondary thread
                    return "result text: "+doLongNetworkOperation();
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(MyObserver);//now this runs in main thread

和MyObserver:

//Observer
Observer MyObserver = new Observer() {
    @Override
    public void onSubscribe(Disposable d) {
        Log.d(TAG,"onSubscribe thread:"+Thread.currentThread().getName());
    }

    @Override
    public void onNext(Object value) {
        Log.d(TAG,"on next, valor:<<"+value.toString()+">> \n nombre hilo:"+Thread.currentThread().getName());
    }

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

    @Override
    public void onComplete() {
        Log.d(TAG,"onCompleted thread:"+Thread.currentThread().getName());
    }
};

请告诉我这是否适合您。