【RxJava Demo分析】(二)Schedulers线程调度器

ConcurrencyWithSchedulersDemoFragment

用Schedulers(调度器)实现多任务(并发,Concurrency)的例子

废话不多说我们看一下有关于RxJava的代码:

    private Subscription _subscription;

    @OnClick(R.id.btn_start_operation) //
    public void startLongOperation() {
        _progress.setVisibility(View.VISIBLE);
        _log("Button Clicked");

        _subscription = _getObservable()//
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(_getObserver());                             // Observer
    }

    private Observable<Boolean> _getObservable() {
        return Observable.just(true).map(new Func1<Boolean, Boolean>() {
            @Override
            public Boolean call(Boolean aBoolean) {
                _log("Within Observable");
                _doSomeLongOperation_thatBlocksCurrentThread();//长时间的操作,阻塞线程
                return aBoolean;
            }
        });
    }

    private Observer<Boolean> _getObserver() {
        return new Observer<Boolean>() {
            //....一些操作
        };
    }

这段代码比较简单,只涉及了一个知识点Schedulers调度器

Schedulers

概括:线程调度器,用来达到切换线程的效果。

在Android开发中,由于UI线程是不能够被阻塞的,不然就会产生ANR导致程序崩溃。所以我们经常的处理是,两种方法:

1.新开线程(或者线程池中)处理阻塞的操作:

        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    mEntity = getEntity();
                    mHandler.obtainMessage(1,mEntity).sendToTarget();
                }catch (Exception e){
                    mHandler.sendEmptyMessage(0);
                }
            }
        }).start();

大家可以看到,我们这里只是进行了一个简单的IO操作,就陷入了这么谜一般的缩进。要是设计更加复杂的呢?

而且我们还要用Handler处理消息,造成了编码的撕裂感! 虽然我个人对Handler并不反感,但在编码的时候,它的存在的确让我感到有点惆怅~~

2.回调处理

        HttpClient.getInstance().get("http://www.qq.com",new HttpCallback(){
            public void onSuccess(String result){
                //...成功操作
            }

            public void onError(Exception e){
                //...失败操作
            }
        });

这里我们随便写了一个获取QQ主页的首页数据的操作。 虽然现在看起来还是蛮简单的。 只有一层回调,但是要是我们要针对QQ返回的结果,再进行一次热门词汇的搜索文章,搜索出来的文章我还要获取第五篇文章,然后我再获取第五篇文章的评论呢?

这里就会陷入Callback Hell (回调地狱)! 维护起来真的是太恶心了!

3.小结一下Schedulers

Schedulers调度器的出现,保持了我们使用RxJava的链式调用,不会出现撕裂感,因为它可以帮我们游刃有余的进行线程切换,而不需要进行Hanlder或者回调!

也正是Schedulers的出现才让我下定决心学习RxJava的初衷! 这实在的太棒了(当然还有无穷无尽的操作符~~)

结束

1.关于Schedulers的原理

因为能力还没有到这里层度,毕竟RxJava和一般的库不一样,它里面涉及了很多“高端知识”而我也不敢乱说出来误导。 所以呢~这里附上前辈的分析吧(反正我看的是有点一头雾水):给 Android 开发者的 RxJava 详解 里面有一部分是涉及Schedulers分析的。

我觉得要是看不懂也没关系,随着我们使用的越来越多,没准在哪一天心血来潮想看看源码的时候突然就明白了呢~

在未来的学习,要是我突然明白了,我会尽快写一篇文章和大家讨论的~

2.附录:完整源代码

public class ConcurrencyWithSchedulersDemoFragment
        extends BaseFragment {

    @Bind(R.id.progress_operation_running)
    ProgressBar _progress;
    @Bind(R.id.list_threading_log)
    ListView _logsList;

    private LogAdapter _adapter;
    private List<String> _logs;
    private Subscription _subscription;

    @Override
    public void onDestroy() {
        super.onDestroy();
        RxUtils.unsubscribeIfNotNull(_subscription);
        ButterKnife.unbind(this);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        _setupLogger();
    }

    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View layout = inflater.inflate(R.layout.fragment_concurrency_schedulers, container, false);
        ButterKnife.bind(this, layout);
        return layout;
    }

    @OnClick(R.id.btn_start_operation)
    public void startLongOperation() {
        _progress.setVisibility(View.VISIBLE);
        _log("Button Clicked");

        _subscription = _getObservable()//
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(_getObserver());                             // Observer
    }

    private Observable<Boolean> _getObservable() {

        return Observable.just(true).map(new Func1<Boolean, Boolean>() {
            @Override
            public Boolean call(Boolean aBoolean) {
                _log("Within Observable");
                _doSomeLongOperation_thatBlocksCurrentThread();
                return aBoolean;
            }
        });
    }

    /**
     * Observer that handles the result through the 3 important actions:
     * <p/>
     * 1. onCompleted
     * 2. onError
     * 3. onNext
     */
    private Observer<Boolean> _getObserver() {
        return new Observer<Boolean>() {

            @Override
            public void onCompleted() {
                _log("On complete");
                _progress.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onError(Throwable e) {
                Timber.e(e, "Error in RxJava Demo concurrency");
                _log(String.format("Boo! Error %s", e.getMessage()));
                _progress.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onNext(Boolean bool) {
                _log(String.format("onNext with return value \"%b\"", bool));
            }
        };
    }

    // -----------------------------------------------------------------------------------
    // Method that help wiring up the example (irrelevant to RxJava)

    private void _doSomeLongOperation_thatBlocksCurrentThread() {
        _log("performing long operation");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            Timber.d("Operation was interrupted");
        }
    }

    private void _log(String logMsg) {
        if (_isCurrentlyOnMainThread()) {
            _logs.add(0, logMsg + " (main thread) ");
            _adapter.clear();
            _adapter.addAll(_logs);
        } else {
            _logs.add(0, logMsg + " (NOT main thread) ");
            // You can only do below stuff on main thread.
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    _adapter.clear();
                    _adapter.addAll(_logs);
                }
            });
        }
    }

    private void _setupLogger() {
        _logs = new ArrayList<String>();
        _adapter = new LogAdapter(getActivity(), new ArrayList<String>());
        _logsList.setAdapter(_adapter);
    }

    private boolean _isCurrentlyOnMainThread() {
        return Looper.myLooper() == Looper.getMainLooper();
    }

    private class LogAdapter
            extends ArrayAdapter<String> {

        public LogAdapter(Context context, List<String> logs) {
            super(context, R.layout.item_log, R.id.item_log, logs);
        }
    }
}

-Hans 2016.3.5 13:36

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,使用 RxJava 可以非常方便地实现线程切换。RxJava 提供了几个操作符用于实现线程切换,包括 `subscribeOn()` 和 `observeOn()`。 `subscribeOn()` 操作符用于指定被观察者的执行线程,而 `observeOn()` 操作符用于指定观察者的执行线程。这两个操作符可以组合使用,实现从一个线程切换到另一个线程的功能。 下面是一个简单的 RxJava 实现多线程的例子: ```java Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { // 在子线程中执行耗时操作 Log.d("RxJava", "subscribe: " + Thread.currentThread().getName()); emitter.onNext(1); emitter.onComplete(); } }) .subscribeOn(Schedulers.newThread()) // 指定被观察者的执行线程 .observeOn(AndroidSchedulers.mainThread()) // 指定观察者的执行线程 .subscribe(new Observer<Integer>() { @Override public void onSubscribe(Disposable d) { // 订阅事件 } @Override public void onNext(Integer integer) { // 处理事件 Log.d("RxJava", "onNext: " + Thread.currentThread().getName()); } @Override public void onError(Throwable e) { // 处理错误 } @Override public void onComplete() { // 完成事件 } }); ``` 在上面的代码中,使用 `subscribeOn()` 操作符指定被观察者在新线程中执行,使用 `observeOn()` 操作符指定观察者在主线程中执行。在实际开发中,可以根据实际需求选择不同的线程。 需要注意的是,RxJava 中的线程切换并不会创建新的线程,而是复用已有的线程。因此,如果需要在多个地方使用 RxJava 进行线程切换,建议使用线程池来管理线程,避免创建过多的线程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值