RxJava notes

Note: This is just a learning process, in order to learn how rxJava is converted from callback nesting, where map and flatMap are just a simplified concept, not the real thing

Thank you

FlatMap does more than encapsulate an item as an Observable. There is also a merge process.

When the synchronization

Response newsList = netApi.getNewsList(0.10);
String title = findLatestTitle(newsList);
Uri uri = netApi.save(title);
Copy the code

Nesting for async

1. Three different interfaces

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. Request network to obtain data **@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. Convert the obtained data to an object */
    public Data tansfer(String s) {
            Data data = GsonUtils.GsonToBean(s, Data.class);
            return data;
    }

    /** * 3. Save some data in the object to */
    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); }}}Copy the code

2. Change the three interfaces to the same interface using genericsonSuccess()The content of the

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. Request network to obtain data **@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. Convert the obtained data to the object **@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. Save some data in the object to */
    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); }}}Copy the code

3. The third step is to make asynchronous methods return values to avoid nesting

An asynchronous operation does not return a value, but we can return a step (Action /Action) that turns the passed argument into a result.

Get an abstract class AsyncJob that receives a Callback with a start() method


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

Copy the code

The start() method is the action to execute,

Back to that

  1. There is no return value when creating an asynchronous task
  2. So we want to return an action that takes the parameter passed in and turns it into a result,AsyncJobIs the return result,start()Is the action
  3. I need this to start the taskCallbackIn, the success/failure result is passed on

Encapsulate the behavior so that after each execution you get a return value (the return value is essentially a method wrapper)

With the result of this behavior encapsulated, you can perform step by step operations like synchronous methods;

What does the map/faltMap operator do

  1. Before use/before extraction

    AsyncJob<Model> modelAsyncJob2 = new AsyncJob<Model>() {
      @Override
      public void start(RxCallback<Model> rxCallback) {
       //responseAsyncJob is the last AsyncJob object
        responseAsyncJob.start(new RxCallback<Response>() {
          @Override
          public void onSuccess(Response response) {
            // All but the following line is template code, so it should be removed
            Model convert = convert(response);
            rxCallback.onSuccess(convert);
          }
    
          @Override
          public void onError(Throwable e) { rxCallback.onError(e); }}); }};Copy the code
  2. After use/after extraction

    //responseAsyncJob is the last AsyncJob object
    AsyncJob<Model> modelAsyncJob1 = responseAsyncJob.map(new FunC1<Response, Model>() {
      @Override
      public Model call(Response response) {
        Model model = convert(response);
        returnmodel; }});Copy the code

  3. What does the map operator do

    public <R> AsyncJob<R> map(FunC1<T, R> funC1) {
      //1. Source is the last resource (the last object)
      AsyncJob<T> source = this;
    
      //2. The new object is the returned object.
      return new AsyncJob<R>() {
    
        //3. Start () {start();
        @Override
        //4. The start() method of this object
        public void start(RxCallback<R> callback) {
    
          //5. Start () method
          source.start(new RxCallback<T>() {
            @Override
            public void onSuccess(T t) {
              //5.5 If the last object's start method succeeded
              // there is an undefined function that declares to convert a parameter of type T to a parameter of type R
              R result = funC1.call(t);
              // 7-a passes on successful results
              callback.onSuccess(result);
            }
    
            @Override
            public void onError(Throwable e) {
              // 7-b passes the resultcallback.onError(e); }}); }}; }Copy the code
  4. What does flatMap do

    public <R> AsyncJob<R> flatMap(FunC1<T, AsyncJob<R>> funC1) {
      //1. Save last object
      AsyncJob<T> source = this;
      //2. Return this object
      return new AsyncJob<R>() {
        //3. This object is executed
        @Override
        public void start(RxCallback<R> callback) {
          //4. The start() method of the previous object is executed first
          source.start(new RxCallback<T>() {
            @Override
            public void onSuccess(T t) {
              //5. Convert one parameter to another AsyncJob object using the abstract action passed in the previous object success
              AsyncJob<R> call = funC1.call(t);
              //6. Call the AsyncJob object's start() method
              call.start(new RxCallback<R>() {
                @Override
                public void onSuccess(R r) {
                  //7. Pass on the results when you succeed
                  callback.onSuccess(r);
                }
    
                @Override
                public void onError(Throwable e) { callback.onError(e); }}); }@Override
            public void onError(Throwable e) { callback.onError(e); }}); }}; }Copy the code

  5. What is the difference between a map and a flatMap?

    The generic type in the received interface in the map is
    ,r>

    The return value of the call method of the Func1 interface in the map operator is an R parameter

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

    The generic type in the interface received in the FlatMap is

    >
    ,observable

    The return value of the call method of the Func1 interface in the FlatMap operator is an Observable

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

Before and after encapsulation

No encapsulation, need to pass the raw method of CallBack (with nested operations)

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); }}); }Copy the code

After the start() function is encapsulated

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;       
}
Copy the code

Encapsulates the map and flatMap operators

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);
      returnmodel; }}); AsyncJob<Uri> uriAsyncJob = modelAsyncJob1.flatMap(new FunC1<Model, AsyncJob<Uri>>() {
    @Override
    public AsyncJob<Uri> call(Model model) {
      AsyncJob<Uri> save = save(model);
      returnsave; }}); }Copy the code

The encapsulation is complete, after lambda

public AsyncJob<Uri> getResult(String url) {
  return netApi.get(url)
    .map(this::convert)
    .flatMap(this::save);
}
Copy the code