【RxJava Demo分析】(一)just、error、defer和CompositeSubscription

前言

RxJava可能是目前最难以掌握的库之一,面对大量的书籍和理论讲解,我选择结合项目来进行理解和记录。

本系列教程是基于Github开源项目RxJava-Android-Samples 进行分析。 里面有RxJava在Android开发中较为日常的使用操作,所以具有非常好的学习意义啊~

但可能因为是英文,可能大家多少有排斥心理,所以我就写下这一系列教程,希望能帮到有意愿学习的童鞋~

注意:因为本人对RxJava也不是非常了解的状态,所以可能会有错误。 希望大家都多批评指正!

教程大纲

本教程主要是截取该开源项目中每一个例子中使用到RxJava的场景,然后进行分析!

分析的时候,会隐藏无关于RxJava的一些代码,但在每篇最后都会贴出完整的源代码

OK 那我们废话不多说啦,直接进入今天的主题:通过分析VolleyDemoFragment学习just、error、defer、CompositeSubscription。

VolleyDemoFragment

    //返回一个JSONObject对象
    private JSONObject getRouteData() throws ExecutionException, InterruptedException {
        ...
        return future.get();
    }

    //已经创建好的
    public Observable<JSONObject> newGetRouteData() {
        return Observable.defer(new Func0<Observable<JSONObject>>() {
            @Override
            public Observable<JSONObject> call() {
                try {
                    //直接将JSONObject对象转为Observable
                    return Observable.just(getRouteData());
                } catch (InterruptedException | ExecutionException e) {
                    Log.e("routes", e.getMessage());
                    //异常处理
                    return Observable.error(e);
                }
            }
        });
    }

     //用了一个奇怪的类~
    private CompositeSubscription _compositeSubscription = new CompositeSubscription();

    //点击按钮之后开始
     private void startVolleyRequest() {
        //用了一个奇怪的类~
        _compositeSubscription.add(newGetRouteData().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JSONObject>() {
                    ...
                }));
    }

知识点有:

1.just操作符

概括:直接将对象转化为Observable对象

一共有7个重载方法,可以接受1-7个参数:
这里写图片描述

调用顺序为: n*onNext+onCompleted(0

2.error操作符

概括:处理异常对象,当调用该方法的时候直接调用onError而不调用onCompleted

3.defer操作符

概括:懒加载 保证数据是最新鲜的。
这个操作符有点难以理解

所以我们这边举一个例子:

        App app = new App("微信");
        Observable<App> obervable = Observable.just(app);
        app = new App("QQ");
        obervable.subscribe(new Observer<App>() {

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable arg0) {

            }

            @Override
            public void onNext(App a) {
                System.out.println(a.getName());
            }
        });

你觉得在onNext输出的信息会是什么? 是微信还是QQ?

大家可能会觉得,应该是QQ吧? 这样想就错了!

实际上使用just创建一个Observable,已经将数据保存好了!

这并不是我们希望看到的结果。

这里有两种解决方式:

1.使用create解决:

这个操作符可以说是最简单的操作符啦~ 在里面创建这个App对象,再封装成Observable。

Observable.create(new OnSubscribe<App>() {
            @Override
            public void call(Subscriber<? super App> s) {
                App a = new App("QQ");
                s.onNext(a);
                s.onCompleted();
            }
        });

这段代码在有订阅的时候才会执行 所以里面的信息可以保证是最新的!

但这个方法好像还是不太完美~ 因为i可能我们希望随时更改这个对象,而不是推迟到创建的时候。

2.使用defer

终于来到重点啦~ 使用这个defer操作符 封装原来的just代码,就可以保证数据是最新的!

private App mApp = new App("微信");

Observable<App> deferObservable = Observable.defer(new Func0<Observable<App>>() {
            @Override
            public Observable<App> call() {
                return Observable.just(mApp);
            }
        });
        mApp = new App("QQ");
        deferObservable.subscribe(new Observer<App>() {

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable arg0) {

            }

            @Override
            public void onNext(App a) {
                System.out.println(a.getName());
            }
        });

被defer封装的操作会推迟到 当有订阅的时候才会执行。所以这就是它的奥秘啦~

这里附上相关分析:RxJava的懒加载,慎重使用自定义操作符,优先考虑内置操作符

3.CompositeSubscription

这个我们先看到 源码注释:

/**
 * Subscription that represents a group of Subscriptions that are unsubscribed together.
 * <p>
 * All methods of this class are thread-safe.
 */

概括:线程安全、由所有订阅者组的组

看看我们上面的实例代码:

_compositeSubscription.add(...);

他将所有的订阅者都添加进去,然后再Activity onPause或者onDestroy时候统一取消订阅,避免造成内存泄漏:

_compositeSubscription.unsubscribe();

结束

1.小结

好的今天的教程就到这里了,我觉得应该每一个都讲的很详细了吧。 希望大家都能理解到啦~~

2.附录:完整源代码

public class VolleyDemoFragment extends BaseFragment {

    public static final String TAG = "VolleyDemoFragment";

    @Bind(R.id.list_threading_log)
    ListView _logsList;

    private List<String> _logs;
    private LogAdapter _adapter;

    private CompositeSubscription _compositeSubscription = new CompositeSubscription();

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

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

    @Override
    public void onPause() {
        super.onPause();
        _compositeSubscription.unsubscribe();
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }

    public Observable<JSONObject> newGetRouteData() {
        return Observable.defer(new Func0<Observable<JSONObject>>() {
            @Override
            public Observable<JSONObject> call() {
                try {
                    return Observable.just(getRouteData());
                } catch (InterruptedException | ExecutionException e) {
                    Log.e("routes", e.getMessage());
                    return Observable.error(e);
                }
            }
        });
    }

    @OnClick(R.id.btn_start_operation)
    void startRequest() {
        startVolleyRequest();
    }

    private void startVolleyRequest() {
        _compositeSubscription.add(newGetRouteData().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JSONObject>() {
                    @Override
                    public void onCompleted() {
                        Log.e(TAG, "onCompleted");
                        Timber.d("----- onCompleted");
                        _log("onCompleted ");
                    }

                    @Override
                    public void onError(Throwable e) {
                        VolleyError cause = (VolleyError) e.getCause();
                        String s = new String(cause.networkResponse.data, Charset.forName("UTF-8"));
                        Log.e(TAG, s);
                        Log.e(TAG, cause.toString());
                        _log("onError " + s);

                    }

                    @Override
                    public void onNext(JSONObject jsonObject) {
                        Log.e(TAG, "onNext " + jsonObject.toString());
                        _log("onNext " + jsonObject.toString());

                    }
                }));
    }

    private JSONObject getRouteData() throws ExecutionException, InterruptedException {
        RequestFuture<JSONObject> future = RequestFuture.newFuture();
        String url = "http://www.weather.com.cn/adat/sk/101010100.html";
        final Request.Priority priority = Request.Priority.IMMEDIATE;
        JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, url, future, future);
        MyVolley.getRequestQueue().add(req);
        return future.get();
    }

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

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

    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 boolean _isCurrentlyOnMainThread() {
        return Looper.myLooper() == Looper.getMainLooper();
    }
}

小吐槽:我对于该作者的代码风格表示有点…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[2\]:上面我们介绍了了关于RxJava的基本的概念和使用方式,在下面的文章中我们会按照以上定义的顺序从API的角度来讲解以下RxJava各个模块的使用方法。引用\[3\]:retry使用了一种错误重试机制,它可以在出现错误的时候进行重试,我们可以通过参数指定重试机制的条件。以下面的程序为例,这里我们设置了当出现错误的时候会进行2次重试,因此,第一次的时候出现错误会调用onNext,重试2次又会调用2次onNext,第二次重试的时候因为重试又出现了错误,因此此时会触发onError方法。也就是说,下面这段代码会触发onNext3次,触发onError()1次。 问题: rxjava2 defer是什么意思? 回答: 在RxJava2中,defer是一个非常有用的操作符。它允许我们在每次订阅时创建一个新的Observable,以便能够动态地生成Observable。defer操作符接受一个Observable的工厂函数作为参数,当有观察者订阅时,它会调用这个工厂函数创建一个新的Observable。这样,每次订阅时都会得到一个全新的Observable实例,可以确保每个订阅者都能够获取到最新的数据。defer操作符的使用场景包括延迟创建Observable、动态地生成Observable等。 #### 引用[.reference_title] - *1* *2* *3* [RxJava 系列-1:一篇的比较全面的 RxJava2 方法总结](https://blog.csdn.net/weixin_34411563/article/details/87985915)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值