煮 Retrofit 论 中华VxJava(一)

率先,本篇是依照这个的总计、思考和展开,那篇小编先易后难,徐徐道来,读起来倍感很棒。

** 壹 、使用Retrofit来开展互连网请求 **

a、互连网接口使用豆瓣电影的top250,大家依照它回到的json格式封装为1个MovieEntity。

https://api.douban.com/v2/movie/top250?start=0&count=10

b、然后创设接口MovieService:

public interface MovieService {
    /** 以Get方法访问接口,参数start和count分别是对接口地址的传参 **/
    @GET("top250")
    Call<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

c、接着,在界面中利用Retrofit进行互联网请求:

private void getMovie() {
        String baseUrl = "https://api.douban.com/v2/movie/";
        /** 创建Retrofit对象,数据转换使用Gson **/
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        /** 通过MoviceService得到Call,然后加入请求队列并,并在Callback接口方法中处理返回结果 **/
        MovieService movieService = retrofit.create(MovieService.class);
        Call<MovieEntity> call = movieService.getTopMovie(0, 10);
        call.enqueue(new Callback<MovieEntity>() {
            @Override
            public void onResponse(Call<MovieEntity> call, Response<MovieEntity> response) {
                resultTV.setText(response.body().toString());
            }

            @Override
            public void onFailure(Call<MovieEntity> call, Throwable t) {
                resultTV.setText(t.getMessage());
            }
        });
    }

正确,以上办法便得以做到请求,可是看起来不美,大家可以通过包装请求方法,在Activity或Fragment中只保留更新UI相关的逻辑。OK,单纯的卷入相比较不难,大家一起参与Evoquexjava来探望。

** ② 、添加本田CR-Vxjava并对请求进度进展封装 **

a、大家事先定义的Service再次回到值就由Call变为Observable了。

public interface MovieService {
    /** 返回的Observable正是被观察者,我们用来通知观察者对象(这里我们通知UI更新) **/
    @GET("top250")
    Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);
}

b、把请求的进度封装到HttpMethods类里面,

public class HttpMethods {
    public static final String BASE_URL = "https://api.douban.com/v2/movie/";
    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit retrofit;
    private MovieService movieService;

    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);

        retrofit = new Retrofit.Builder()
                .client(httpClientBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                //此处添加RxJavaCallAdapterFactory,把请求结果直接映射为
                //MovieService接口方法返回的具体类型MovieEntity
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        movieService = retrofit.create(MovieService.class);
    }

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

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

    /**
     * 用于获取豆瓣电影Top250的数据
     * @param subscriber  由调用者传过来的观察者对象
     * @param start 起始位置
     * @param count 获取长度
     */
    public void getTopMovie(Subscriber<MovieEntity> subscriber, int start, int count){
        movieService.getTopMovie(start, count)
                //指定subscribe()发生在io调度器(读写文件、读写数据库、网络信息交互等)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                //指定subscriber的回调发生在主线程
                .observeOn(AndroidSchedulers.mainThread())
                //实现订阅关系
                .subscribe(subscriber);
    }
}

c、那么getMovie()方法直接调用封装过的getTopMovie()即可。从中,大家看来使用CR-Vxjava带来两点变化:二个是将呼吁封装进Observable;其余是透过完毕Subscriber中的四个接口方法来打招呼请求状态(即UI更新)。

   private void getMovie() {
        subscriber = new Subscriber<MovieEntity>() {
            @Override
            public void onCompleted() {
                Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(Throwable e) {
                resultTV.setText(e.getMessage());
            }

            @Override
            public void onNext(MovieEntity movieEntity) {
                /** 这里得到的请求结果直接是我们想要的java对象 **/
                resultTV.setText(movieEntity.toString());
            }
        };
        HttpMethods.getInstance().getTopMovie(subscriber, 0, 10);
    }

从地点大家知晓Retrofit会把重回的json对象映射为大家要求的java对象,大家的使用中必然会用到很多网络接口,大家明天是伸手的影片列表,大家还会呈请电影详情,歌唱家详情等等,那大家就要求定义MovieDetail、Actor等等Entity。难题是咱们的劳动普通会给咱们回来三个定位样式的数目,形如:

{
 "resultCode": 1,
 "resultMsg": "成功",
 "data": {}
}

并且大家常见会先去判断resultCode,以便可以统一处理错误消息。至于data中的结构,则是浮动的,它可以是影视列表Movies,也得以是歌星音讯Actor,那么此时大家就会回想使用泛型来开展打包:

public class HttpResult<T> {
    private int resultCode;
    private String resultMsg;
    private T data;
}

若果data是Actor对象的话,那么定义Service方法再次回到值就可以写成:

observable<HttpResult<Actor>>

假如data是影片列表,那么大家得以如此写:

observable<HttpResult<List<Movie>>>

2018年全年资料大全,设想到一般列表的数码都会有分页音讯,大家还可以继续封装:

/** 支持分页的json结构 **/
{
 "start": 0,
 "count": 20,
 "total": 250
 "list": []
}
/** 封装后带分页的泛型对象 **/
public class HttpResList<T> {
    private int start;
    private int count;
    private int total;
    private T list;
}

那么电影列表,就要求这么写了:

observable<HttpResult<HttpResList<List<Movie>>>>

嗬啊啊,是或不是有一种碟中谍、局中局的痛感…当然,为了缩短层级,我们得以把分页的连锁消息涉及resultCode那几个层级来,这一个必要大家跟服务端协定好一个平整。

那么封装为泛型后的代码跟上边的距离不大,只是把Observable相关的参数或重返类型由MovieEntity改为HttpResult<List<Movie>>(注意,我们所采纳的测试接口跟我们上述商讨的构造有出入),全部就不再贴出代码。

所以,协定好二个专业、好用的数据结构,是多么的酸爽。

骨子里,作者平昔有个怀疑,为何要用普拉多xjava呢?没见到代码简洁、好用啊,是呀,Why?请移步
煮 Retrofit 论 RxJava(二)

转发请标明出处:http://www.jianshu.com/p/86cf7de684b3

发表评论

电子邮件地址不会被公开。 必填项已用*标注