Retrofit与RxJava的结合使用

前面我已经介绍过了RxJava的使用,现在我们来学习Retrofit的简单使用

Retrofit是一个当前很流行的网络请求库, 官网的介绍是: "Type-safe HTTP client for Android and Java". 本文介绍Retrofit的使用.
先介绍单独使用Retrofit进行网络请求, 后面主要介绍和RxJava结合的请求, 有实例代码.

在使用Retrofit之前我们需要在androidstudio中依赖下面三个库

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
我们现在以Git的API为例子 https://api.github.com

先建立一个实体类Endpoints

这个API实体的变量太多了这里就不放出代码了

首先我们需要写一个接口GitHubService

public interface GitHubService {
    @GET
    Call getAllEndpoints(@Url String url);
}
这个接口指定了一个Get请求,用来传Url的

public interface GitHubService {
    @GET
    Call getAllEndpoints(@Url String url);
}

然后我们再创建一个类,利用Retrofit发送请求并

public class ServiceGenerator {

    private static ServiceGenerator instance;

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    private static Retrofit.Builder builder;

    public ServiceGenerator(String url) {
        builder = new Retrofit.Builder()
                        .baseUrl(url)
                        .addConverterFactory(GsonConverterFactory.create());
    }

    public  static ServiceGenerator getInstance(String url){
        if(null == instance){
            synchronized (ServiceGenerator.class){
                instance = new ServiceGenerator(url);
            }
        }
        return instance;
    }

    public static  S createService(Class serviceClass) {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}
最后请求并得到结果

public class MainActivity extends Activity {
    public static final String API_BASE_URL = "https://api.github.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GitHubService gitHubService = ServiceGenerator.getInstance(API_BASE_URL).createService(GitHubService.class);
        Call endpointsCall = gitHubService.getAllEndpoints("");
        endpointsCall.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Endpoints endpoints = response.body();
                String repositoryUrl = endpoints.getRepository_url();
                Log.e("repository url:",repositoryUrl);
                Toast.makeText(MainActivity.this, "repository url: " + repositoryUrl, Toast.LENGTH_LONG).show();
            }
            @Override
            public void onFailure(Call call, Throwable t) {

            }
        });
      
    }
}

如果请求是多参数的, user_url是:https://api.github.com/users/{user}

public interface GitHubService {
    @GET
    Call getAllEndpoints(@Url String url);

    @GET("users/{user}")
    Call getUser(@Path("user") String user);
}

Retrofit和RxJava结合使用

RxJava近年来很流行, 主要优势是流式操作, 可以处理并行发送请求, 使用灵活, 线程切换容易.
当你要处理的逻辑比较复杂时, 就会发现使用RxJava的优势.

以我们的例子来说, 当前我们利用一个请求可以得到一个用户的信息并显示出来.
如果我们想得到这个用户的所有repo的所有者或者其他信息, 所有他follow的人的信息, 以及他们的repo的信息呢?

这就需要发很多个请求, 并且其中有些请求是并行发送的, 如果按照前面的方法, 不断地在callback里面嵌套, 那就太难看了.

首先, 添加RxJava和RxAndroid的依赖:

compile 'io.reactivex:rxjava:1.2.2'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
Retrofit.Builder()中加入这一行:.addCallAdapterFactory(RxJavaCallAdapterFactory.create());

public class ServiceGenerator {
    public static final String API_BASE_URL = "https://api.github.com";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create());

    public static  S createService(Class serviceClass) {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}
现在改用RxJava了, 返回的不是Call而是Observable:

@GET("users/{user}/following")
Observable> getUserFollowingObservable(@Path("user") String user);
结合RxJava请求的时候变为这样:
还是请求用户follow的所有人:

GitHubService service = ServiceGenerator.createService(GitHubService.class);
String username = inputUserNameView.getText().toString();
service.getUserFollowingObservable(username)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(List users) {
                LogUtils.i("onNext: " + users.size());
                peopleListAdapter.setUsers(users);
                peopleListAdapter.notifyDataSetChanged();
            }
        });

RxJava处理多个请求的例子

设计这样一个场景, 我们现在取到了一个用户follow的所有人, 但是取回的信息中并不包含每个人拥有的repo个数, 只有一个url可用户查看所有repo.

接下来我们要取其中每一个人的详细信息, 就要查询另一个API, 重新查询这个人的完整信息.
查询用户follow的所有人, 然后查询每一个人的详细信息:

subscription = service.getUserFollowingObservable(username)
        .flatMap(new Func1, Observable>() {
            @Override
            public Observable call(List users) {
                return Observable.from(users);
            }
        })
        .flatMap(new Func1>() {
            @Override
            public Observable call(User user) {
                return service.getUserObservable(user.getLogin());
            }
        })
        .toList()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(List users) {
                peopleListAdapter.setUsers(users);
                peopleListAdapter.notifyDataSetChanged();
            }
        });
我们会发现我们每次取user数据的时候有点慢我们可以这样:

subscription = service.getUserFollowingObservable(username)
        .subscribeOn(Schedulers.io()) // 从io线程开始, 取用户follow的所有人
        .flatMap(new Func1, Observable>() {
            @Override
            public Observable call(List users) {
                LogUtils.i("from");
                return Observable.from(users);
            }
        })
        .toList()
        .observeOn(AndroidSchedulers.mainThread()) // 最后返回到主线程
        .subscribe(new Subscriber>() {
            @Override
            public void onCompleted() {

            }
            @Override
            public void onError(Throwable e) {

            }
            @Override
            public void onNext(List users) {
                LogUtils.i("onNext: " + users.size());
                peopleListAdapter.setUsers(users);
                peopleListAdapter.notifyDataSetChanged();
            }
        })

取消订阅

当我们有时跳转界面时,网络请求还没有完成,这样很可能没有请求返回,这样就可能引起内存泄漏,所以我们需要自己取消订阅

   @Override
    protected void onPause() {
        super.onPause();
        if (subscription!= null && subscription.isUnsubscribed()){
            subscription.unsubscribe();
        }
    }
如果有多个请求, 可以用:

private CompositeSubscription compositeSubscription = new CompositeSubscription();

...
// 在发请求的地方, 返回subscription
compositeSubscription.add(subscription);
...

// 选一个生命周期注销所有请求
@Override
public void onPause() {
    super.onPause();
    compositeSubscription.unsubscribe();
}




你可能感兴趣的:(安卓)