美文网首页三方框架Retrofit网络请求
Android 网络(四) Retrofit学习笔记

Android 网络(四) Retrofit学习笔记

作者: 合肥黑 | 来源:发表于2016-08-18 22:40 被阅读470次

    参考
    Android开源项目推荐之「网络请求哪家强」
    野生西瓜--[Android] Retrofit 初步使用
    野生西瓜--[Android] Retrofit 源码分析之执行流程
    野生西瓜--[Android] Retrofit 源码分析之 Retrofit 对象
    Retrofit使用教程(一)
    Retrofit使用教程(二)
    Retrofit使用教程(三):Retrofit与RxJava初相逢
    深入浅出 Retrofit
    快速Android开发系列网络篇之Retrofit
    Retrofit2 完全解析 探索与okhttp之间的关系
    拆轮子系列:拆 Retrofit
    'Retrofit源码1: 为什么写一个interface就可以实现http请求'

    一、概念

    Retrofit 是 Square 公司出品的默认基于 OkHttp 封装的一套 RESTful 网络请求框架,不了解 RESTful 概念的不妨去搜索学习下,RESTful 可以说是目前流行的一套 api 设计的风格,并不是标准。Retrofit 的封装可以说是很强大,里面涉及到一堆的设计模式,你可以通过注解直接配置请求,你可以使用不同的 http 客户端,虽然默认是用 http ,可以使用不同 Json Converter 来序列化数据,同时提供对 RxJava 的支持,使用** Retrofit + OkHttp + RxJava + Dagger2 **可以说是目前比较潮的一套框架,但是需要有比较高的门槛。

    Retrofit与picasso一样都是在okhttp基础之上做的封装,项目中可以直接用了。Retrofit因为也是Square出的,所以大家可能对它更崇拜些。Retrofit跟Volley是一个套路,但解耦的更彻底:比方说通过注解来配置请求参数,通过工厂来生成CallAdapter,Converter,你可以使用不同的请求适配器(CallAdapter), 比方说RxJava,Java8, Guava。你可以使用不同的反序列化工具(Converter),比方说json, protobuff, xml, moshi等等。炒鸡解耦,里面涉及到超多设计模式,个人觉得是很经典的学习案例。虽然支持Java8, Guava你可能也不需要用到。xml,protobuff等数据格式你也可能不需要解析。but,万一遇到鬼了呢。至于性能上,个人觉得这完全取决于请求client,也就是okhttp的性能,跟这些封装工具没太大关系。

    Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是 Retrofit 来完成的。Retrofit 2.0 开始内置 OkHttp,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作,宛如古人的『你耕地来我织布』,小日子别提多幸福了。

    我们的应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,后者根据用户的需求对结果进行解析的过程。讲到这里,你就会发现所谓 Retrofit,其实就是 Retrofitting OkHttp 了。

    二、例一

    参考野生西瓜--[Android] Retrofit 初步使用
    1.定义接口

    public interface APIInterface {
      @GET("/users/{user}")
      Call<TestModel> repo(@Path("user") String user);
    }
    

    GET 的意思是 发送一个 GET请求,请求的地址为:baseUrl + "/users/{user}"。{user} 类似于占位符的作用,具体类型由 repo(@Path("user") String user) 指定,这里表示 {user} 将是一段字符串。
    Call<TestModel> 是一个请求对象,<TestModel>表示返回结果是一个 TestModel 类型的实例。

    public class TestModel {
      private String login;
      public String getLogin() {
        return login;
      }
      public void setLogin(String login) {
        this.login = login;
      }
    }
    

    2.构造一个 Retrofit 对象:

    Retrofit retrofit= new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();
    

    注意这里添加的 baseUrl 和 GsonConverter,前者表示要访问的网站,后者是添加了一个JSON转换器。

    3.创建API 接口对象

    APIInterface service = retrofit.create(APIInterface.class);
    Call<TestModel> model = service.repo("Guolei1130");
    

    注意这里的 .repo("Guolei1130") 取代了前面的 {user}。到这里,我们要访问的地址就成了:
    https://api.github.com/users/Guolei1130
    可以看出这样的方式有利于我们使用不同参数访问同一个 Web API 接口,比如你可以随便改成 .repo("ligoudan")

    4.最后,就可以发送请求了!

    model.enqueue(new Callback<TestModel>() {
      @Override
      public void onResponse(Call<TestModel> call, Response<TestModel> response) {
        // Log.e("Test", response.body().getLogin());
        System.out.print(response.body().getLogin());
      }
    
      @Override
      public void onFailure(Call<TestModel> call, Throwable t) {
        System.out.print(t.getMessage());
      }
      });
    

    5.另外,说说POST 请求参数设置
    POST 的请求与 GET 请求不同,POST 请求的参数是放在请求体内的。所以当我们要为 POST 请求配置一个参数时,需要用到 @Body 注解:

    Call<TestModel> post(@Body User user);
    //这里的 User 类型是需要我们去自定义的:
    public class User {
      public String username;
      public String password;
    
      public User(String username,String password){
        this.username = username;
        this.password = password;
    }
    //最后在获取请求对象时:
    User user = new User("lgd","123456");
    Call<TestModel> model = service.post(user);
    
    三、例二

    参考Retrofit使用教程(一)
    使用的是百度的API Store提供的API,地址在此:手机号码归属地__API服务_API服务_API Store.
    1.设置model
    访问该API返回的数据格式如下:

    {
        "errNum": 0,
        "retMsg": "success",
        "retData": {
            "phone": "15210011578",
            "prefix": "1521001",
            "supplier": "移动",
            "province": "北京",
            "city": "北京",
            "suit": "152卡"
        }
    }
    

    根据返回结果我们创建数据对象PhoneResult,如下:

    public class PhoneResult {
        /**
         * errNum : 0
         * retMsg : success
         * retData : {"phone":"15210011578","prefix":"1521001","supplier":"移动","province":"北京","city":"北京","suit":"152卡"}
         */
        private int errNum;
        private String retMsg;
        /**
         * phone : 15210011578
         * prefix : 1521001
         * supplier : 移动
         * province : 北京
         * city : 北京
         * suit : 152卡
         */
        private RetDataEntity retData;
    
        public void setErrNum(int errNum) {
            this.errNum = errNum;
        }
    
        public void setRetMsg(String retMsg) {
            this.retMsg = retMsg;
        }
    
        public void setRetData(RetDataEntity retData) {
            this.retData = retData;
        }
    
        public int getErrNum() {
            return errNum;
        }
    
        public String getRetMsg() {
            return retMsg;
        }
    
        public RetDataEntity getRetData() {
            return retData;
        }
    
        public static class RetDataEntity {
            private String phone;
            private String prefix;
            private String supplier;
            private String province;
            private String city;
            private String suit;
    
            public void setPhone(String phone) {
                this.phone = phone;
            }
    
            public void setPrefix(String prefix) {
                this.prefix = prefix;
            }
    
            public void setSupplier(String supplier) {
                this.supplier = supplier;
            }
    
            public void setProvince(String province) {
                this.province = province;
            }
    
            public void setCity(String city) {
                this.city = city;
            }
    
            public void setSuit(String suit) {
                this.suit = suit;
            }
    
            public String getPhone() {
                return phone;
            }
    
            public String getPrefix() {
                return prefix;
            }
    
            public String getSupplier() {
                return supplier;
            }
    
            public String getProvince() {
                return province;
            }
    
            public String getCity() {
                return city;
            }
    
            public String getSuit() {
                return suit;
            }
        }
    }
    

    2.构造接口

    public interface PhoneService {
        @GET("/apistore/mobilenumber/mobilenumber")
        Call<PhoneResult> getResult(@Header("apikey") String apikey, @Query("phone") String phone);
    }
    

    3.使用

    private static final String BASE_URL = "http://apis.baidu.com";
    private static final String API_KEY = "8e13586b86e4b7f3758ba3bd6c9c9135";
    
    private void query(){
        //1.创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())//解析方法
                .baseUrl(BASE_URL)//主机地址
                .build();
                
        //2.创建访问API的请求
        PhoneService service = retrofit.create(PhoneService.class);
        Call<PhoneResult> call = service.getResult(API_KEY, phoneView.getText().toString());
        
        //3.发送请求
        call.enqueue(new Callback<PhoneResult>() {
            @Override
            public void onResponse(Call<PhoneResult> call, Response<PhoneResult> response) {
                //4.处理结果
                if (response.isSuccess()){
                    PhoneResult result = response.body();
                    if (result != null){
                        PhoneResult.RetDataEntity entity = result.getRetData();
                    }
                }
            }
    
            @Override
            public void onFailure(Call<PhoneResult> call, Throwable t) {
    
            }
        });
    }
    
    四、query,head

    参考Retrofit使用教程(二)
    1.query

    //如12306的查询接口https://kyfw.12306.cn/otn/lcxxcx/query?
    //purpose_codes=ADULT&queryDate=2016-03-18&from_station=BJP&to_station=CDW,写法如下:
    @GET("/otn/lcxxcx/query")
    Call<Result> query(@Query("purpose_codes") String codes, @Query("queryDate") String date,
        @Query("from_station") String from, @Query("to_station") String to)
    

    2.head

    //比如要更新某个账户信息,其接口地址为/info,需要带的Header有设备信息device,
    //系统版本version,还要带请求参数要更新账户的id,代码如下:
    @POST("/info")
    Call<Object> updateInfo(@Header("device") String device, @Header("version") int version,
                            @Field("id") String id);
    
    五、Retrofit中使用RxJava

    参考Retrofit使用教程(三):Retrofit与RxJava初相逢

    //使用RxJava我们则返回一个可被观测的PhoneResult:Observable<PhoneResult>,如下:
    @GET("/apistore/mobilenumber/mobilenumber")
    Observable<PhoneResult> getPhoneResult(@Header("apikey") String apikey,
                                           @Query("phone") String phone);
    //为了能返回此对象,我们需要在创建Retrofit对象时添加一个RxJava对象的Adapter来自动完成:
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    //获取手机的归属地
    phoneService.getPhoneResult(PhoneApi.API_KEY, number)
            .subscribeOn(Schedulers.newThread())    //子线程访问网络
            .observeOn(AndroidSchedulers.mainThread())  //回调到主线程
            .subscribe(new Observer<PhoneResult>() {
                @Override
                public void onCompleted() {}
    
                @Override
                public void onError(Throwable e) {}
    
                @Override
                public void onNext(PhoneResult result) {
                    if (result != null && result.getErrNum() == 0) {
                        PhoneResult.RetDataEntity entity = result.getRetData();
                        resultView.append("地址:" + entity.getCity());
                    }
                }
            });
    }
    

    相关文章

      网友评论

        本文标题:Android 网络(四) Retrofit学习笔记

        本文链接:https://www.haomeiwen.com/subject/qvhpsttx.html