• [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
    
  • 相关阅读:
    业务需求、用户需求和功能需求
    乐观锁的两种实现方式
    数据字典
    freemarker(ftl)标签用法
    commons-lang常用方法
    前端与后端分离
    jar包导入本地maven库的操作
    本地打jar包到本地的Maven出库
    MyEclipse中好用的快捷键汇总整理
    简单的反编译class文件并重新编译的方法
  • 原文地址:https://www.cnblogs.com/assassin-l/p/5088963.html
Copyright © 2020-2023  润新知