[RxJava^Android]项目经验分享 --- 失败重试

简单介绍一下业务逻辑:获取字符串,如果获取失败进行10次重试,超出10次未成功视为失败。

模拟获取字符串场景

代码块

   class MsgTool {
        int count;
        String getMsg() throws Exception {
            count++;
            LogUtils.d("execute getMsg count : " + count);
            if (count == 15) {
                return "getMsg";
            } else {
                throw new Exception("exception getMsg");
            }
        }
    }

Java代码实现逻辑(实现方式很多种,这里不是重点)

代码块

    public void testMain() {
        LogUtils.d("result : " + getSyncMsg());
    }

    private String getSyncMsg() {
        MsgTool msgTool = new MsgTool();
        String result = null;
        boolean isSuccess = false;
        int count = 0;
        while ((count < 10) && !isSuccess) {
            try {
                result = msgTool.getMsg();
                isSuccess = true;
            } catch (Exception e) {
                count++;
            }
        }
        return result;
    }

输出结果

23:33:14.908 32364-32377/? D/LogUtils: execute getMsg count : 1
23:33:14.908 32364-32377/? D/LogUtils: execute getMsg count : 2
23:33:14.908 32364-32377/? D/LogUtils: execute getMsg count : 3
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 4
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 5
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 6
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 7
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 8
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 9
23:33:14.909 32364-32377/? D/LogUtils: execute getMsg count : 10
23:33:14.909 32364-32377/? D/LogUtils: result : null

针对上述业务逻辑改为RxJava实现,使用操作符retry可实现

代码块

    public void testMain() {
        getSyncMsg().subscribe(getSubscriber());
    }

    private Observable<String> getSyncMsg() {
        MsgTool msgTool = new MsgTool();
        Observable<String> o = Observable.create(subscriber -> {
            try {
                subscriber.onNext(msgTool.getMsg());
                subscriber.onCompleted();
            } catch (Exception e) {
                subscriber.onError(e);
            }
        });
        return o.retry(10);
    }
    
    private Subscriber<Object> getSubscriber() {
        return new Subscriber<Object>() {
            @Override
            public void onCompleted() {
                LogUtils.d("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                LogUtils.d("onError : " + e.toString());
            }

            @Override
            public void onNext(Object o) {
                LogUtils.d("onNext : " + o);
            }
        };
    }

输出结果

23:45:43.761 3285-3307/? D/LogUtils: execute getMsg count : 1
23:45:43.762 3285-3307/? D/LogUtils: execute getMsg count : 2
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 3
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 4
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 5
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 6
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 7
23:45:43.763 3285-3307/? D/LogUtils: execute getMsg count : 8
23:45:43.764 3285-3307/? D/LogUtils: execute getMsg count : 9
23:45:43.764 3285-3307/? D/LogUtils: execute getMsg count : 10
23:45:43.764 3285-3307/? D/LogUtils: execute getMsg count : 11
23:45:43.765 3285-3307/? D/LogUtils: onError : java.lang.Exception: exception getMsg

下面我们增加一个业务逻辑,每次重试延迟一秒种。此功能不做Java代码实现(使用定时器、Android系统下使用Handler等),而用RxJava代码实现,虽然看着很迷糊,但是慢慢品味就会发觉它的魅力所在。

    public void testMain() {
        getSyncMsg().subscribe(getSubscriber());
    }

    private Observable<String> getSyncMsg() {
        MsgTool msg = new MsgTool();
        Observable<String> o = Observable.create(subscriber -> {
            try {
                subscriber.onNext(msg.getMsg());
                subscriber.onCompleted();
            } catch (Exception e) {
                subscriber.onError(e);
            }
        });

        return o.retryWhen(this::delayRetry);
    }

     //此方法就是魅力的所在
    private Observable<Object> delayRetry(Observable<? extends Throwable> o) { 
        return o.zipWith(Observable.range(1, 10),   //控制10次以内
                (throwable, integer) -> {
                    if (integer == 10) {        //如果是最后一次,结合的结果是异常。
                        return throwable;
                    } else {
                        return integer;
                    }
                })
                .flatMap(object -> Observable.create(subscriber -> {
                    //转换retryWhey发射的数据
                    if (object instanceof Throwable) {
                        subscriber.onError((Throwable) object);
                    } else {
                        subscriber.onNext(o);
                        subscriber.onCompleted();
                    }
                }).delay(1, TimeUnit.SECONDS));     //延迟一秒发射
    }

    private Subscriber<Object> getSubscriber() {
        return new Subscriber<Object>() {
            @Override
            public void onCompleted() {
                LogUtils.d("onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                LogUtils.d("onError : " + e.toString());
            }

            @Override
            public void onNext(Object o) {
                LogUtils.d("onNext : " + o);
            }
        };
    }

输出结果

00:36:57.271 19355-19372/? D/LogUtils: onStart
00:36:57.297 19355-19372/? D/LogUtils: execute getMsg count : 1
00:36:58.305 19355-19377/? D/LogUtils: execute getMsg count : 2
00:36:59.306 19355-19404/? D/LogUtils: execute getMsg count : 3
00:37:00.307 19355-19375/? D/LogUtils: execute getMsg count : 4
00:37:01.308 19355-19376/? D/LogUtils: execute getMsg count : 5
00:37:02.308 19355-19377/? D/LogUtils: execute getMsg count : 6
00:37:03.309 19355-19404/? D/LogUtils: execute getMsg count : 7
00:37:04.309 19355-19375/? D/LogUtils: execute getMsg count : 8
00:37:05.310 19355-19376/? D/LogUtils: execute getMsg count : 9
00:37:06.311 19355-19377/? D/LogUtils: execute getMsg count : 10
00:37:06.320 19355-19377/? D/LogUtils: onError : java.lang.Exception: exception getMsg
原文地址:https://www.cnblogs.com/assassin-l/p/5088963.html