[07]——RxJava与Retrofit的简单使用

Retrofit

现在Android开发中,主流的网络请求库有Retrofit、OkHttp、Volley等,最热门的就是Retrofit了。

Retrofit官方的介绍是:A type-safe REST client for Android and Java(类型安全的REST客户端for 安卓&Java)

RESTful可以参考这篇文章,本文只做Retrofit的介绍以及配合RxJava使用上的简单介绍,本文中的Retrofit指retrofit:2.1.0版本;

1 Retrofit的简单使用

添加依赖:

//reteofit最新版本为2.1.0
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.google.code.gson:gson:2.6.2'

1.1 发起一次请求

  1. 创建Retrofit实例
       Retrofit retrofit = new Retrofit.Builder()
               .baseUrl("https://api.github.com/")
                //json转换器,retrofit支持多种json转换器(Gson、Jackson、Moshi),需要添加不同的依赖
               .addConverterFactory(GsonConverterFactory.create())  
               .build();

注意:Retrofit的实例其实相当于一个http client,其底层实现默认使用的是OkHttp。因此在实际开发中,只需要存在一个实例即可,应当对其进行一次单例封装;baseUrl中的字符串必须要以“/”作为结尾,且其中不能含有如“?”之类的字符,否则会抛出java.long.IllegalArgumentException:baseUrl must end in /"

  1. 创建请求接口
    在Retrofit中,所有的请求应当按照要求声明在一个interface中,如下所示:
       public interface GitHubService {
         @GET("users/{user}/repos")
         Call<List<Repo>> listRepos(@Path("user") String user);  //@Path注解的参数会添加到url中
       }

其中@GET注解中的内容会与被添加到Retrofit实例中的baseUrl拼接,形成完整的Url;

  1. 发起请求
GitHubService service = retrofit.create(GitHubService.class);  //获取请求接口实例
Call<List<Repo>> call = service.listRepos("octocat");    //创建请求对象
//同步请求
try {
      List<Repo> repos = call.execute();
} catch (IOException e) {
      e.printStackTrace();
}
    //异步请求
   call.enqueue(new Callback<List<Repo>>() {
       @Override
       public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
           //请求成功
       }
       @Override
       public void onFailure(Call<List<Repo>> call, Throwable t) {
           //请求出错
       }
   });
  1. 取消请求
        call.cancel();

1.2 请求接口

URL MANIPULATION (Url操作)

A request URL can be updated dynamically using replacement blocks and parameters on the method. A replacement block is an alphanumeric string surrounded by { and }. A corresponding parameter must be annotated with @Path using the same string.
一个请求的Url可以通过使用占位符与请求接口中方法的参数来动态更新,占位符通过字符{}包括。占位符中的字符必须与@Path注解中的字符相同。

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
//当参数为groupList(1)时,请求的url将为https://api.github.com/group/1/users

Query parameters can also be added.
可以同时添加查询参数,使用@Query注解

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
//当参数为groupList(1,2)时,请求的url将为https://api.github.com/group/1/users/sort/2

For complex query parameter combinations a Map can be used.
复杂的请求参数可以使用@QueryMap 注解,添加一个map参数

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

REQUEST BODY (请求体)

An object can be specified for use as an HTTP request body with the @Body annotation.
可以通过@Body 注解来将一个对象作为请求体使用在一次HTTP请求中。

@POST("users/new")
Call<User> createUser(@Body User user);

The object will also be converted using a converter specified on the Retrofit instance. If no converter is added, only RequestBody can be used.
//这个对象将通过实例化Retrofit时声明的JSON转换器转换成JSON字符串,如果没有添加转换器,那么被@Body 注解的参数只可以是RequestBody对象

表单编码、多请求、以及请求头操作大家可以自行查看文档,本文不作过多介绍;

2 Retrofit与RxJava配合使用

通过我们声明的请求接口方法我们可以看出,当我们通过请求接口获取一个请求时,创建的是一个Call<T>的实例,然后通过调用call.execute();或者call.enqueue(new Callback<T>() {});来执行同步请求或者异步请求。

Retrofit天生支持RxJava,首先我们需要要添加compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'依赖。

修改创建Retrofit实例的代码为如下样式

Retrofit retrofit = new Retrofit.Builder():
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        //添加RxJava适配器
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

修改请求接口中方法的返回值为如下样式:

public interface GitHubService {
  @GET("users/{user}/repos")
   Observable<List<Repo>> listRepos(@Path("user") String user);  //@Path注解的参数会添加到url中
}

可以看出,我们只是在创建Retrofit实例时,为其增加了RxJava的适配器,并将创建请求的返回值改成了Observable(被观察者)。如果你熟悉RxJava那么接下来的事情就顺理成章了,我们不需要关心网络请求如何完成,只需要将对List<Repo>的相关操作,按照RxJava的方式书写即可。

 service.listRepos("octocat")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<List<Repo>>() {
            @Override
            public void onCompleted() {
                //执行成功
            }

            @Override
            public void onError(Throwable e) {
                //抛出异常
            }

            @Override
            public void onNext(List<Repo> repos) {
                //对发射的数据进行操作
            }
        });

3 简单封装

上文中我们提到了Retrofit对象只需要一个实例,同时我们的请求接口GitHubService也只需要一个实例。所以我们应当将这两个实例封装在一个单例中。

public class HttpMethods {

    public static final String BASE_URL = "https://api.github.com/";

    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit mRetrofit;
    private GitHubService mGitHubService;
    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        //创建唯一的retrofit实例与请求接口实例
        mRetrofit = new Retrofit.Builder()
                .client(builder.build())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        mGitHubService = mRetrofit.create(GitHubService.class);
    }

    //在访问HttpMethods时创建单例
    private static class SingletonHolder{
        private static final HttpMethods INSTANCE = new HttpMethods();
    }

    //获取单例
    public static HttpMethods getInstance(){
        return SingletonHolder.INSTANCE;
    }

    /**
     * 对被观察者进行注册操作
     * @param observable
     * @param subscriber
     * @param <T>
     */
    private <T> void toSubscribe(Observable<T> observable, Subscriber<T> subscriber){
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }
    //声明我们的请求
    public void listRepos(String user,Subscriber<List<Repo>> subscriber){
        Observable observable = mGitHubService.listRepos(user);
        toSubscribe(observable,subscriber);
    }
}

在需要发起网络请求的位置执行如下代码:

Subscriber subscriber = new Subscriber<List<Repo>>() {
    @Override
    public void onCompleted() {
        Logger.d("complete!!!");
    }

    @Override
    public void onError(Throwable e) {
        Logger.e(e, "");
    }

    @Override
    public void onNext(List<Repo> repos) {
        Logger.json(new Gson().toJson(repos));
    }

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

推荐阅读更多精彩内容