Retrofit、RxJava和OkHttp使用

本文主要介绍Retrofit、RxJava和OkHttp使用。需要添加依赖:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'

这里需要注意RxJava的版本问题,如果使用的是RxJava2,那么一定要使用adapter-rxjava2,否则在编码时会找不到相关的类。

Retrofit单独使用

  1. Retrofit的请求是通过注解来实现的,需要先建一个接口类。
public interface RetrofitService {

    @GET("book/search")
    Call<Book> getBook(@Query("q") String name,
                       @Query("tag") String tag,
                       @Query("start") int start,
                       @Query("count") int count);
}

这是一个get请求,"book/search"是用来拼接请求url的,@Query("tag") String tag是用来传入请求参数的。

  1. 得到Call对象执行网络请求
Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("https://api.douban.com/v2/")
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
                RetrofitService retrofitService = retrofit.create(RetrofitService.class);
                Call<Book> call = retrofitService.getBook("西游记", null, 0, 1);
                call.enqueue(new Callback<Book>() {
                    @Override
                    public void onResponse(Call<Book> call, Response<Book> response) {
                        Book book = response.body();
                        mTvContent.setText(book + "");
                    }

                    @Override
                    public void onFailure(Call<Book> call, Throwable t) {

                    }
                });

这是Retrofit单独使用时候的用法。新建一个Retrofit对象,用这个Retrofit对象通过接口类可以得到一个Call对象,直接用这个Call对象发起网络请求,里面有两个回调方法供我们处理请求结果。

Retrofit和RxJava使用

  1. 在接口类中再写一个方法
public interface RetrofitService {

    @GET("book/search")
    Call<Book> getBook(@Query("q") String name,
                       @Query("tag") String tag,
                       @Query("start") int start,
                       @Query("count") int count);

    @GET("book/search")
    Observable<Book> getSearchBook(@Query("q") String name,
                                   @Query("tag") String tag,
                                   @Query("start") int start,
                                   @Query("count") int count);
}

可以看到,两个方法的写法都一样,只是返回值由Call对象变成了RxJava中的Observable对象。
关于RxJava的介绍,可以阅读以下这篇文章
给 Android 开发者的 RxJava 详解

  1. 得到Observable对象执行网络请求
 Retrofit retrofitRxjava = new Retrofit.Builder()
                        .baseUrl("https://api.douban.com/v2/")
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .build();
                RetrofitService retrofitService1 = retrofitRxjava.create(RetrofitService.class);
                Observable<Book> observable = retrofitService1.getSearchBook("西游记", null, 0, 1);
                observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<Book>() {
                            @Override
                            public void onSubscribe(@NonNull Disposable d) {
                                Log.d("AAA", "aaa");
                            }

                            @Override
                            public void onNext(@NonNull Book book) {
                                Log.d("BBB", "bbb");
                                mTvContent.setText(book + "");
                            }

                            @Override
                            public void onError(@NonNull Throwable e) {
                                Log.d("DDD", "ddd");
                            }

                            @Override
                            public void onComplete() {
                                Log.d("CCC", "ccc");
                            }
                        });

基本步骤都是一样的,在构建Retrofit对象时,我们多添加了addCallAdapterFactory(RxJava2CallAdapterFactory.create())这一行代码,网络请求的回调方法也发生了改变。
四个回调方法,先执行onSubscribe()方法,表示订阅完成;然后执行onNext()方法,在这个方法中,我们可以获取网络请求的结果,并进行处理(在这个Demo中,请求得到一个Book对象,把Book对象中的文本内容显示在一个TextView中);最后执行onComplete()方法,表示整个网络请求过程完成。可以从下图的log日志中看到它们的执行顺序。

回调方法执行顺序

这是Demo请求成功之后的效果图。

网络请求成功

如果网络请求失败,则会执行onError()方法。这里我把网络关闭了,onError()方法报错显示无法连接上那个地址。注意这里只会执行onSubscribe()方法和onError()方法,不会再执行onNext()方法,也不会执行onComplete()方法。


回调方法执行顺序

Retrofit、RxJava和OkHttp一起使用

在了解了Retrofit、RxJava的使用之后,再加入一个OkHttp。其实这并不复杂,Retrofit内部也是通过OkHttp来实现网络请求的。我们可以用自己定义的OkHttpClient来代替Retrofit默认的OkHttpClient,然后在自定义的OkHttpClient中添加一些配置,比如配置网络请求的超时时间、配置缓存等等。
我们对Retrofit的网络请求进行一个简单的二次封装,这样在Activity或Fragment中使用起来更加方便,代码更加简洁,可维护程度更高。

新建一个RetrofitInstance类。在RetrofitInstance类中,创建一个OkHttpClient对象,配置了它的超时时间。再写一个单例模式,返回Retrofit对象,并且把自定义的OkHttpClient设置进去。(通过自定义的OkHttpClient,我们可以对网络请求做很多配置,具体请参考OkHttp使用教程

public class RetrofitInstance {

    private static Retrofit sInstance;

    private static OkHttpClient mClient = new OkHttpClient().newBuilder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .build();

    private RetrofitInstance() {
    }

    public static Retrofit getRetrofitInstance() {
        if (sInstance == null) {
            synchronized (RetrofitInstance.class) {
                if (sInstance == null) {
                    sInstance = new Retrofit.Builder()
                            .client(mClient)
                            .baseUrl("https://api.douban.com/v2/")
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .build();
                }
            }
        }
        return sInstance;
    }

}

在Activity中使用Retrofit网络请求,不用每次都新建Retrofit对象,直接使用单例方法来获取就行了。回调方法和前面的也还是一样的。

RetrofitService retrofitService2 = RetrofitInstance.getRetrofitInstance().create(RetrofitService.class);
                Observable<Book> bookObservable = retrofitService2.getSearchBook("西游记", null, 0, 1);
                bookObservable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<Book>() {
                            @Override
                            public void onSubscribe(@NonNull Disposable d) {
                                Log.d("AAA", "aaa");
                            }

                            @Override
                            public void onNext(@NonNull Book book) {
                                Log.d("BBB", "bbb");
                                mTvContent.setText(book + "");
                            }

                            @Override
                            public void onError(@NonNull Throwable e) {
                                Log.d("DDD", e.toString());
                            }

                            @Override
                            public void onComplete() {
                                Log.d("CCC", "ccc");
                            }
                        });

这就是Retrofit、RxJava和OkHttp最基本的使用。也许看起来代码还是挺多的,那是因为RxJava的强大之处远不在此,遇到复杂的情况才能体现出它的优越性。如果你感兴趣,推荐你阅读一下这篇文章给 Android 开发者的 RxJava 详解

最后附上Book实体类的代码(因为比较长)。

public class Book {
    
    private int count;
    private int start;
    private int total;
    
    private List<BooksBean> books;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public List<BooksBean> getBooks() {
        return books;
    }

    public void setBooks(List<BooksBean> books) {
        this.books = books;
    }

    public static class BooksBean {
        
        private RatingBean rating;
        private String subtitle;
        private String pubdate;
        private String origin_title;
        private String image;
        private String binding;
        private String catalog;
        private String pages;
        private ImagesBean images;
        private String alt;
        private String id;
        private String publisher;
        private String isbn10;
        private String isbn13;
        private String title;
        private String url;
        private String alt_title;
        private String author_intro;
        private String summary;
        private String price;
        private List<String> author;
        private List<TagsBean> tags;
        private List<String> translator;

        public RatingBean getRating() {
            return rating;
        }

        public void setRating(RatingBean rating) {
            this.rating = rating;
        }

        public String getSubtitle() {
            return subtitle;
        }

        public void setSubtitle(String subtitle) {
            this.subtitle = subtitle;
        }

        public String getPubdate() {
            return pubdate;
        }

        public void setPubdate(String pubdate) {
            this.pubdate = pubdate;
        }

        public String getOrigin_title() {
            return origin_title;
        }

        public void setOrigin_title(String origin_title) {
            this.origin_title = origin_title;
        }

        public String getImage() {
            return image;
        }

        public void setImage(String image) {
            this.image = image;
        }

        public String getBinding() {
            return binding;
        }

        public void setBinding(String binding) {
            this.binding = binding;
        }

        public String getCatalog() {
            return catalog;
        }

        public void setCatalog(String catalog) {
            this.catalog = catalog;
        }

        public String getPages() {
            return pages;
        }

        public void setPages(String pages) {
            this.pages = pages;
        }

        public ImagesBean getImages() {
            return images;
        }

        public void setImages(ImagesBean images) {
            this.images = images;
        }

        public String getAlt() {
            return alt;
        }

        public void setAlt(String alt) {
            this.alt = alt;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getPublisher() {
            return publisher;
        }

        public void setPublisher(String publisher) {
            this.publisher = publisher;
        }

        public String getIsbn10() {
            return isbn10;
        }

        public void setIsbn10(String isbn10) {
            this.isbn10 = isbn10;
        }

        public String getIsbn13() {
            return isbn13;
        }

        public void setIsbn13(String isbn13) {
            this.isbn13 = isbn13;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getAlt_title() {
            return alt_title;
        }

        public void setAlt_title(String alt_title) {
            this.alt_title = alt_title;
        }

        public String getAuthor_intro() {
            return author_intro;
        }

        public void setAuthor_intro(String author_intro) {
            this.author_intro = author_intro;
        }

        public String getSummary() {
            return summary;
        }

        public void setSummary(String summary) {
            this.summary = summary;
        }

        public String getPrice() {
            return price;
        }

        public void setPrice(String price) {
            this.price = price;
        }

        public List<String> getAuthor() {
            return author;
        }

        public void setAuthor(List<String> author) {
            this.author = author;
        }

        public List<TagsBean> getTags() {
            return tags;
        }

        public void setTags(List<TagsBean> tags) {
            this.tags = tags;
        }

        public List<String> getTranslator() {
            return translator;
        }

        public void setTranslator(List<String> translator) {
            this.translator = translator;
        }

        public static class RatingBean {
            private int max;
            private int numRaters;
            private String average;
            private int min;

            public int getMax() {
                return max;
            }

            public void setMax(int max) {
                this.max = max;
            }

            public int getNumRaters() {
                return numRaters;
            }

            public void setNumRaters(int numRaters) {
                this.numRaters = numRaters;
            }

            public String getAverage() {
                return average;
            }

            public void setAverage(String average) {
                this.average = average;
            }

            public int getMin() {
                return min;
            }

            public void setMin(int min) {
                this.min = min;
            }

            @Override
            public String toString() {
                return "RatingBean{" +
                        "max=" + max +
                        ", numRaters=" + numRaters +
                        ", average='" + average + '\'' +
                        ", min=" + min +
                        '}';
            }
        }

        public static class ImagesBean {
            private String small;
            private String large;
            private String medium;

            public String getSmall() {
                return small;
            }

            public void setSmall(String small) {
                this.small = small;
            }

            public String getLarge() {
                return large;
            }

            public void setLarge(String large) {
                this.large = large;
            }

            public String getMedium() {
                return medium;
            }

            public void setMedium(String medium) {
                this.medium = medium;
            }

            @Override
            public String toString() {
                return "ImagesBean{" +
                        "small='" + small + '\'' +
                        ", large='" + large + '\'' +
                        ", medium='" + medium + '\'' +
                        '}';
            }
        }

        public static class TagsBean {
            private int count;
            private String name;
            private String title;

            public int getCount() {
                return count;
            }

            public void setCount(int count) {
                this.count = count;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public String getTitle() {
                return title;
            }

            public void setTitle(String title) {
                this.title = title;
            }
        }

        @Override
        public String toString() {
            return "BooksBean{" +
                    "rating=" + rating +
                    ", subtitle='" + subtitle + '\'' +
                    ", pubdate='" + pubdate + '\'' +
                    ", origin_title='" + origin_title + '\'' +
                    ", image='" + image + '\'' +
                    ", binding='" + binding + '\'' +
                    ", catalog='" + catalog + '\'' +
                    ", pages='" + pages + '\'' +
                    ", images=" + images +
                    ", alt='" + alt + '\'' +
                    ", id='" + id + '\'' +
                    ", publisher='" + publisher + '\'' +
                    ", isbn10='" + isbn10 + '\'' +
                    ", isbn13='" + isbn13 + '\'' +
                    ", title='" + title + '\'' +
                    ", url='" + url + '\'' +
                    ", alt_title='" + alt_title + '\'' +
                    ", author_intro='" + author_intro + '\'' +
                    ", summary='" + summary + '\'' +
                    ", price='" + price + '\'' +
                    ", author=" + author +
                    ", tags=" + tags +
                    ", translator=" + translator +
                    '}';
        }
    }

    @Override
    public String toString() {
        return "Book{" +
                "count=" + count +
                ", start=" + start +
                ", total=" + total +
                ", books=" + books +
                '}';
    }
}

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

推荐阅读更多精彩内容