RxJava学习,封装一个简单的map 和flatMap

RxJava 笔记

注意:这只是学习的过程,为了学习rxjava是怎么由callback嵌套转换而来,其中的map和flatMap 都只是精简过后的一个概念,不是真正的样子

感谢

W_BinaryTree
2楼 · 2017.05.12 01:07
flatMap不仅仅是把item封装成observable。 还有个merge的过程。

同步时

Response newsList = netApi.getNewsList(0,10);
String title = findLatestTitle(newsList);
Uri uri = netApi.save(title);

异步时嵌套

1. 三个不同的接口

public class MainActivity extends AppCompatActivity {
    String url = "http://op.juhe.cn/yi18/news/newsclass";

    interface ApiCallback {
        void onSuccess(String data);

        void onError(Throwable e);
    }


    interface TransferCallback {
        void onSuccess(Data data);

        void onError(Throwable e);
    }

    interface ResultCallback {
        void onSuccess(Uri uri);

        void onError(Throwable e);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("ss", "sss");
        findViewById(R.id.btn).setOnClickListener(v -> {
            request(new ApiCallback() {
                @Override
                public void onSuccess(String data) {
                            Data dat = tansfer(data);
                            save(data, new ResultCallback() {
                                @Override
                                public void onSuccess(Uri uri) {
                                }

                                @Override
                                public void onError(Throwable e) {
                                }
                            });
                    });
                }
                @Override
                public void onError(Throwable e) {
                }
            });
        });
    }

    /**
     * 1. 请求网络获取数据
     *
     * @param apiCallback
     */
    public void request(ApiCallback apiCallback) {
        OkGo.get(url)
                .params("key", "2e6f34e3fe8fa96e5384021477f8e224")
                .execute(new StringCallback() {

                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        Log.d("MainActivity", "onSuccess: " + s);
                        apiCallback.onSuccess(s);
                    }

                    @Override
                    public void onError(Call call, Response response, Exception e) {
                        apiCallback.onError(e);
                    }
                });
    }

    /**
     * 2. 将获取的数据转换成对象
     */
    public Data tansfer(String s) {
            Data data = GsonUtils.GsonToBean(s, Data.class);
            return data;
    }

    /**
     * 3.将对象中的某个数据保存
     */
    public void save(Data data, ResultCallback resultCallback) {
        try {
            ResultBean result = data.getResult();
            ListBean list = result.getList();
            List<TngouBean> tngou = list.getTngou();

            String s = GsonUtils.GsonString(list);
            SharedPreferences config = getSharedPreferences("config", MODE_PRIVATE);
            config.edit().putString("tag", s).apply();

            resultCallback.onSuccess(Uri.parse(s));
        } catch (Throwable e) {
            resultCallback.onError(e);
        }
    }
}

2. 将三个接口改为同一个接口,用泛型来确定onSuccess()的内容

public class MainActivity extends AppCompatActivity {
    String url = "http://op.juhe.cn/yi18/news/newsclass";

    interface Callback<T> {
        void onSuccess(T data);

        void onError(Throwable e);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("ss", "sss");
        findViewById(R.id.btn).setOnClickListener(v -> {
            request(new Callback<String>() {
                @Override
                public void onSuccess(String data) {
                    tansfer(data, new Callback<Data>() {
                        @Override
                        public void onSuccess(Data data) {
                            save(data, new Callback<Uri>() {
                                @Override
                                public void onSuccess(Uri uri) {
                                }

                                @Override
                                public void onError(Throwable e) {
                                }
                            });
                        }
                        @Override
                        public void onError(Throwable e) {
                        }
                    });
                }
                @Override
                public void onError(Throwable e) {
                }
            });

        });
    }

    /**
     * 1. 请求网络获取数据
     *
     * @param apiCallback
     */
    public void request(Callback apiCallback) {
        OkGo.get(url)
                .params("key", "2e6f34e3fe8fa96e5384021477f8e224")
                .execute(new StringCallback() {

                    @Override
                    public void onSuccess(String s, Call call, Response response) {
                        Log.d("MainActivity", "onSuccess: " + s);
                        apiCallback.onSuccess(s);
                    }

                    @Override
                    public void onError(Call call, Response response, Exception e) {
                        apiCallback.onError(e);
                    }
                });
    }

    /**
     * 2. 将获取的数据转换成对象
     *
     * @param transferCallback
     */
    public void tansfer(String s, Callback transferCallback) {
        try {
            Data data = GsonUtils.GsonToBean(s, Data.class);
            transferCallback.onSuccess(data);
        } catch (Throwable throwable) {
            transferCallback.onError(throwable);
        }
    }

    /**
     * 3.将对象中的某个数据保存
     */
    public void save(Data data, Callback resultCallback) {
        try {
            ResultBean result = data.getResult();
            ListBean list = result.getList();
            List<TngouBean> tngou = list.getTngou();

            String s = GsonUtils.GsonString(list);
            SharedPreferences config = getSharedPreferences("config", MODE_PRIVATE);
            config.edit().putString("tag", s).apply();

            resultCallback.onSuccess(Uri.parse(s));
        } catch (Throwable e) {
            resultCallback.onError(e);
        }
    }
}

3. 第三步,让异步方法有返回值,从而避免嵌套

异步操作是没有返回值的,但是我们可以返回一个可以把传递进来的参数变成结果的步骤(动作/Action)

获得一个抽象类AsyncJob 这个AsyncJob 接收一个Callback ,有一个start() 的方法


public interface AsyncJob<T> {
    void start(Callback<T> callback);
}

这个start() 方法就是要执行的动作,

回到刚才话题

  1. 创建异步任务的时候是没有返回值的
  2. 所以我们要返回一个含有将传递进来的参数转变成结果的动作,AsyncJob 是返回结果,start()就是动作
  3. 启动这个任务的时候需要的这个Callback中则会将成功/失败的结果传递出去

将行为封装后,这样每次执行后就可以获得一个返回值(这个返回值实际上就是一个方法包装)

这样行为的封装结果有了,那么就可以像同步方法一样执行一步一步的操作了;

map/faltMap操作符做了点什么

  1. 使用前/抽离前

    AsyncJob<Model> modelAsyncJob2 = new AsyncJob<Model>() {
      @Override
      public void start(RxCallback<Model> rxCallback) {
       //responseAsyncJob 是上个AsyncJob对象
        responseAsyncJob.start(new RxCallback<Response>() {
          @Override
          public void onSuccess(Response response) {
            //除了下面这一行其他都是模板代码,所以应该抽离出来
            Model convert = convert(response);
            rxCallback.onSuccess(convert);
          }
    
          @Override
          public void onError(Throwable e) {
            rxCallback.onError(e);
          }
        });
      }
    };
    
  2. 使用后/抽离后

    //responseAsyncJob 是上个AsyncJob对象
    AsyncJob<Model> modelAsyncJob1 = responseAsyncJob.map(new FunC1<Response, Model>() {
      @Override
      public Model call(Response response) {
        Model model = convert(response);
        return model;
      }
    });
    

  3. map操作符做了点什么

    public <R> AsyncJob<R> map(FunC1<T, R> funC1) {
      //1. source 就是上一个资源 (上次对象)
      AsyncJob<T> source = this;
    
      //2. 这里的new 对象就是返回的对象(简称本次对象)
      return new AsyncJob<R>() {
    
        //3. 这里表示本次执行(start())的时候,(调用start方法的时候,会去先执行上个对象的start()方法)
        @Override
        //4. 本个对象的start()方法
        public void start(RxCallback<R> callback) {
    
          //5. 上个对象start()方法
          source.start(new RxCallback<T>() {
            @Override
            public void onSuccess(T t) {
              //5.5 如果上个对象的start方法成功了
              //6.0这里有一个不确定的函数,这个函数声明了将一个T,类型的参数转换为一个R类型
              R result = funC1.call(t);
              //7 -a将成功结果传递出去
              callback.onSuccess(result);
            }
    
            @Override
            public void onError(Throwable e) {
              //7- b 将结果传递出去
              callback.onError(e);
            }
          });
        }
      };
    }
    
  4. flatMap 做了点什么

    public <R> AsyncJob<R> flatMap(FunC1<T, AsyncJob<R>> funC1) {
      //1. 保存上个对象
      AsyncJob<T> source = this;
      //2. 返回本次对象
      return new AsyncJob<R>() {
        //3. 表示本次对象执行
        @Override
        public void start(RxCallback<R> callback) {
          //4. 表示执行时首先会执行上个对象的start()方法
          source.start(new RxCallback<T>() {
            @Override
            public void onSuccess(T t) {
              //5. 在上个对象成功中使用传入的抽象动作,将一个参数转换为另外一个AsyncJob对象
              AsyncJob<R> call = funC1.call(t);
              //6. 调用这个AsyncJob对象的start()方法
              call.start(new RxCallback<R>() {
                @Override
                public void onSuccess(R r) {
                  //7. 在成功时将结果传递出去
                  callback.onSuccess(r);
                }
    
                @Override
                public void onError(Throwable e) {
                  callback.onError(e);
                }
              });
            }
    
            @Override
            public void onError(Throwable e) {
              callback.onError(e);
            }
          });
        }
      };
    }
    

  5. mapflatMap 是哪里不一样?

map 中接收的接口中的泛型是<T,R>

说明map操作符中Func1接口的call方法的返回值是一个R类型的参数

  @Override
  public Model call(Response response) {
    Model model = convert(response);
    return model;
  }

flatmap 中接收的接口中的泛型是<T,Observable<R>>

说明flatmap 操作符中Func1 接口的call方法的返回值是一个Observable<R>类型的参数

@Override
public AsyncJob<Uri> call(Model model) {
  AsyncJob<Uri> save = save(model);
  return save;
}

封装完成前后的对比

没有进行封装,需要传递CallBack的原始方法(含有嵌套操作)

public void getResult(String url, RxCallback<Uri> rxCallback) {
  netApi.get(url, new RxCallback<Response>() {
    @Override
    public void onSuccess(Response response) {
      Model model = convert(response);

      save(model, new RxCallback<Uri>() {
        @Override
        public void onSuccess(Uri uri) {
          rxCallback.onSuccess(uri);
        }

        @Override
        public void onError(Throwable e) {
          rxCallback.onError(e);
        }
      });
    }

    @Override
    public void onError(Throwable e) {
      rxCallback.onError(e);
    }
  });
}

使用封装了start()函数后

public AsyncJob<Uri> getResult(String url) {
  AsyncJob<Response> responseAsyncJob = netApi.get(url);
  AsyncJob<Model> modelAsyncJob = new AsyncJob<Model>() {
    @Override
    public void start(RxCallback<Model> rxCallback) {
      responseAsyncJob.start(new RxCallback<Response>() {
        @Override
        public void onSuccess(Response response) {
          Model convert = convert(response);
          rxCallback.onSuccess(convert);
        }

        @Override
        public void onError(Throwable e) {
          rxCallback.onError(e);
        }
      });
    }
  };

  AsyncJob<Uri> uriAsyncJob = new AsyncJob<Uri>() {
    @Override
    public void start(RxCallback<Uri> rxCallback) {
      modelAsyncJob.start(new RxCallback<Model>() {
        @Override
        public void onSuccess(Model model) {
          AsyncJob<Uri> save = save(model);
          save.start(new RxCallback<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
              rxCallback.onSuccess(uri);
            }

            @Override
            public void onError(Throwable e) {
              rxCallback.onError(e);
            }
          });
        }

        @Override
        public void onError(Throwable e) {
          rxCallback.onError(e);
        }
      });
    }
  };
  return uriAsyncJob;       
}

封装了map操作符 和flatMap 操作符

public AsyncJob<Uri> getResult(String url) {
  AsyncJob<Response> responseAsyncJob = netApi.get(url);
  AsyncJob<Model> modelAsyncJob1 = responseAsyncJob.map(new FunC1<Response, Model>() {
    @Override
    public Model call(Response response) {
      Model model = convert(response);
      return model;
    }
  });
  AsyncJob<Uri> uriAsyncJob = modelAsyncJob1.flatMap(new FunC1<Model, AsyncJob<Uri>>() {
    @Override
    public AsyncJob<Uri> call(Model model) {
      AsyncJob<Uri> save = save(model);
      return save;
    }
  });
}

封装完成 ,lambda化后

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

推荐阅读更多精彩内容

  • 前言我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占导zqq阅读 9,157评论 6 151
  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,442评论 7 62
  • 前言RxJava和Retrofit也火了一段时间了,不过最近一直在学习ReactNative和Node相关的姿势,...
    AFinalStone阅读 530评论 0 0
  • 文章转自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物线在正...
    xpengb阅读 7,007评论 9 73
  • 古时候的人,晚上出门一定很不方便,没有整晚明晃晃的便捷的路灯,只有一盏纸糊的素色灯笼,风雨飘摇。若是家贫,无以立足...
    Hebetow阅读 223评论 0 3