我们为什么要用rxjava?

好久没有写技术性文章了。最近趁着工作不是特别忙,再一次拿出一些时间研究Rxjava。在研究的过程中,我发现自己进展比较慢,在回过头来反省自己的时候,发现我可能连一些基本的问题还没有搞清楚就开始研究RXJAVA,相当于地基还没有打好,就开始修建高楼大厦。这些基本的问题里有一个最核心的问题:我们为什么要用Rxjava?

关于这个问题,不用说我,相信很多现在正在使用rxjava的人可能都不一定想的很透彻,大多都是人云亦云,随波逐流。李笑来说过:我们在这个世界上最宝贵的财富--注意力容易掉进三个坑,而随波逐流就是这其中一个坑。所以为了不让自己掉进这么一个坑,也打算在继续研究Rxjava前,先解决这个问题:我们为什么要用rxjava.

首先要先理清这么一个问题:Rxjava和我们平时写的程序有什么不同。相信稍微对Rxjava有点认知的朋友都会深深感受到用这种方式写的程序和我们一般写的程序有很明显的不同。我们一般写的程序 统称为命令式程序,是以流程为核心的,每一行代码实际上都是机器实际上要执行的指令。而Rxjava这样的编程风格,称为函数响应式编程。函数响应式编程是以数据流为核心,处理数据的输入,处理以及输出的。这种思路写出来的代码就会跟机器实际执行的指令大相径庭。所以对于已经习惯命令式编程的我们来说,刚开始接触Rxjava的时候必然会很不适应,而且也不太符合我们平时的思维习惯。

那么问题来了,既然函数响应式编程如此的不符合我们的惯性思维,那么为什么我们越来越多的人开始尝试运用rxJava以及函数响应式编程思想来写程序了呢?

不如我们直接从实例来入手好了。我们设想这么一个简单的实例,一个小的图书管理应用,我现在要做的是根据图书的ID号从服务器取得该图书的信息,并且做了修改再提交回去。很简单的一个业务逻辑,主要是和大家一起体验思维过程。

首先我们应该先写出书籍这个对象的实体类:

      public class Book{
         public int id;
         public String name;
         public String author;     

      }

然后我们再来写对书籍进行网络调用的接口:

     public interface IBookService{ 
         public Book getBookById(int bookId); 
         public void updateBook(Book book);
    }

相信这个接口大家并不难理解,一个是根据id从服务器得到该Book对象,另一个方法就是提交修改后的book 对象到服务器,具体实现在这里就不详细说明了哈,在这里就假设有个类DefaultBookService实现了该接口。那么我们开始实现业务层的逻辑:

      public class BookBusiness{ 
         private IBookService mService; 
        public BookBusiness(){ 
           mService = new DefaultBookService(); 
        } 
     
      public void updateBook(int bookId){ 
          Book book = mService.getBookById(bookId); 
             if(book!=null){ 
               //book.setAuthor("小7"); 
               book.aughor = "小7";
               mService.updateBook(book); 
             } 
       } 
   }

这个方法好像也并不难理解,也不复杂。那么我们不就可以不需要用什么函数响应式编程就可以了吗?

先别急,我们看看上面的代码有没有问题呢?对了,我们上面的代码一直是在用主线程来进行网络请求调用!而在我们实际的项目中,网络请求是一定要异步线程调用的,这样才不会出现线程阻塞的问题。所以我们需要修改一下代码:

     public interface Callback<T>{ 
        public void onResult(T result); 
        public void onError(Exception exception);
    }
     public interface IBookService{ 
       public void getBookById(int bookId,Callback<Book> callback); 
       public void updateBook(Book book ,Callback<void> callback);
    }

这段代码增加了一个回调接口以便在服务器请求后通过回调方法把结果回传给业务层。

     public class BookBusiness{ 
        private IBookService mService; 
        public BookBusiness(){ 
          mService = new DefaultBookService(); 
        } 
      
      public void updateBook(int bookId,Callback<Void> callback){ 
          mService.getBookById(1,new Callback<Book>{ 
                   public void onResult(Book result){ 
                         if(result!=null){ 
                            result.author="小7"; 
                            mService.updateBook(result,callback); 
                         } 
                   }
                  
                  public void onError(Exception exception){
                        callback.onError(exception);
                   }
                     }); 
            } 
            }

这样在我们的业务代码里面就会有匿名类,可读性自然就下降。我们这个时候可以想想办法,看如何消除掉匿名类。这个时候我们可以考虑在请求调用的方法里仅仅返回一个临时对象来封装实际的网络请求。

    public class Task<T>{
          public void doHandle(Callback<T> callback);
    }


这个时候我们需要在IBookService上面封装一层:

   public class BookServiceWrapper{ 
      private IBookService mService; 
      public BookServiceWrapper(){ 
         mService = new DefaultBookService(); 
      } 
      public Task<Book> getBookById(int bookId){ 
         return new Task<Book>(){ 
            public void doHandle(Callback<Book> callback){ 
                mService. getBookById(bookId,callback); 
              } 
         }; 
      } 
     public Task<Void> updateBook(final Book book){ 
         return new Task<Void>{ 
            public void doHandle(final Callback<Void> callback){ 
                            mService.updateBook(book,callback); 
             } 
         }; 
       }
  }

这样业务层的代码由原来的直接对接口的引用转为对这个封装的类的引用:

public class BookBusiness{ 
  private BookServiceWrapper mWrapper; 
  public BookBusiness(){ 
     mWrapper = new BookServiceWrapper(); 
  } 
  public Task<Void> updateBook(int bookId){ 
     return new Task<Void>(){ 
         public void doHandle(final Callback<Void> callback){ 
                mWrapper.getBookById.doHandle(new Callback<Book>(){
                    public void onResult(Book result){ 
                       if(result!=null){ 
                         result.setAuthor("小7"); 
                         mWrapper.updateBook(result).doHandle(callback); 
                         } 
                     }
                 public void onError(Exception exception){
                      callback.onError(exception);
                 }
             } ); 
        } 
       } 
     }
   }

这样做好像并没有明显提高代码的可读性。那么我们开始继续优化。其实我们看代码里复杂的地方就是嵌套了不少Callback回调类。那么我们可以想想是否可以把callback分离开来呢?我们可以先定义一个代表函数的接口。

     public interface Func<T,R>{
       public R call(T parameter);
     }

有了这个接口定义后,我们可以实现一个Task抽象类来把这个代表函数的接口用上。

   public abstract class AbstractTask<T> implements Task<T>{ 
      public abstract void do Hanlde(Callback<T> callback); 
     portected <R> AbstractTask<R> map(Func<T,AbstractTask<R>> func){ 
       AbstractTask<T> origin = this; 
      return new AbstractTask<R>{ 
        public void doHandle(final Callback<R> rCallback){ 
           origin.doHandle(new Callback<T>(){ 
                public void onResult(T result){ 
                    AbstractTask<R> rTask = func.call(result);
                    rTask.doHandle(callback);
                  } 
                
                public void onError(Exception exception){
                  rCallback.onError(exception);
                     
               }
}); 
} } } }

看完这个实现,是不是思路逐渐明朗起来,我们在业务层里不需要再处理callback了:

   public class BookBusiness{ 
      private BookServiceWrapper mWrapper; 
      public BookBusiness(){ 
           mWrapper = new BookServiceWrapper(); 
      } 
     public AbstractTask<Void> updateBook(int bookId){ 
          AbstractTask<Book> bookTask = mWrapper.getBookById(bookId); 
          AbstractTask<Void> baseTask = bookTask.map(new Func<Book,AbstractTask<Void>>(){ 
             public AbstractTask<Void> call(Book book){ 
             bookTask.updateBook(book);
       } 
         }); 
   } 
   } 
 }
 }

现在,我们的推导完成了。大家有没有眼前一亮的感觉,当前的这段代码非常优雅的分离了业务代码和callback回调代码。而我们的AbstractTask类相当于Rxjava里面的Observable,Callback类相当于Observer。我这么说完,你是否看出了Rxjava的影子了呢。是不是很好的解决了我们的代码复杂度的问题了呢?

以上就是我一步步把我们的传统的编程思维转换为函数式相应编程的思维实现了自己的rxjava框架,当然rxjava框架远远不仅仅是这么点,但是我也希望通过自己的这点解释也能让大家真正开始明白我们为什么要使用函数式响应编程思想,这样采才能更加深入掌握它,也希望大家能多多交流,一起成长。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,810评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 从小学就知道海水是咸的 但直到21岁我才亲自去尝了一次 《够》 相册放在立柜上 很久不碰落满了灰 要不时地擦擦 我...
    纳兰苏浅阅读 416评论 0 0
  • No cached version available for offline mode 翻译过来就是脱机模式下没...
    zhongjh阅读 13,430评论 2 2
  • 11床 姓名: 性别:年龄:诊断: 这是一位入院病人的简介,而在我们眼里,这只是一位患者,来时不请自来,走时皆大...
    阿羊ai阅读 212评论 1 0