简体   繁体   中英

How to avoid callback hell in Java?

I have java app with sequence of api calls (I'm using retrofit). Currently it looks like pyramid:

mApi.login(request, new Callback<LoginResponse>() {
  @Override
  public void success(LoginResponse s, Response response) {
     mApi.getRoutes(request, new Callback<RoutesResponse>() {
        @Override
        public void success(RoutesResponses, Response response) {
           ...
        }
        @Override
        public void failure(RetrofitError error) {}
     }
  }

   @Override
   public void failure(RetrofitError error) {}
});

Are there some libraries to avoid callback hell? like TwoStep or Q in javascript.

Using lambda expressions will get rid of this kind of callback hell.But, since Callback<T> interface consists of 2 abstract methods, you cannot directly use lambdas. This is where RxJava kicks in. RxJava introduces more functional way and enables you to use functional interfaces where you can use lambda to reduce callback hell.

RxJava is a Java VM implementation of ReactiveX (Reactive Extensions): a library for composing asynchronous and event-based programs by using observable sequences...

Here is some resources about RxJava and lambda.

As long as you are sequencing just the API calls, you can employ Retrofit's RxJava support by using Observables instead of callbacks and tying them together with the Rx stream support. I mostly use .flatmap() function to convert result of one API call to another. In your case, it would like something like this:

First I will be using the Observable version of the calls instead of the ones with callbacks, which will be:

Observable<LoginResponse> login(loginRequest);
Observable<RoutesResponse> getRoutes(routesRequest);

After we have these two functions in our API, we can tie them together with RxJava streams. Here is one without error checking, I am writing this on the go to show as a quick example:

public Observable<RoutesResponse> rxGetRoutes(loginRequest, routesRequest) {
  final YourAPI mAPI = YourApiProvider.getInstance();

  return mAPI.login(loginRequest)
    //using flatmap to convert one answer to another answer
    .flatmap( (Func1) LoginResponse -> {
      return mAPI.getRoutes(routesRequest); 
    });
}

You can now observe and subscribe to the returned Observable of this function as normal, after learning RxJava a bit:

rxGetRoutes(loginReq, routesReq)
   .observeOn(//the thread you want to observe on)
   .subscribe( new Subscriber<RoutesResult>() {
          @Override
          //the functions of Subscriber you need to override
          //where you can also check for errors
          //Check RxJava documentation after your IDE completes this area.
                 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM