框架学习| Retrofit2.x(一)

开新坑辣!一直觉得自己框架了解的特别少,大多只知其名而不知实现原理,然而几乎每次面试都会被问及框架。所以很有必要总结一些常用的框架,希望自己能坚持把这个『框架学习』系列的新坑填的厚实一点!

先从网络框架中大名鼎鼎的Retrofit开始吧,本篇先对Retrofit有个了解,目录如下:

  • 概述
  • 使用方式

1.概述

a.Retrofit是Square公司推出的一个基于RESTful风格的HTTP网络框架。

相关链接地址:

b.与OkHttp的关系:

是对OkHttp网络请求框架的二次封装,本质仍是OkHttp。即网络请求的工作本质上是由OkHttp完成,而Retrofit仅负责网络请求接口的封装。流程如图:

  • App应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由OkHttp完成后续的请求操作。
  • 在服务端返回数据之后,OkHttp将原始的结果交给Retrofit,Retrofit会根据用户的需求对结果进行解析。
  • 通过使用大量的设计模式进行功能模块的解耦,使得上面的过程进行得更加简单和流畅。

c.其他网络框架简介:

  • AndroidAsynHttp:基于HttpClient,已经停止维护,Android5.0不再使用HttpClient。
  • Volley:基于HttpUrlConnection,由谷歌官方推出,适合轻量级网络交互,如数据传输量小的场景,而不适合大文件传输。

相比于上述两种网络框架,Retrofit具有的优点

  • 遵循Restful API设计风格,简洁易用
  • 支持同步&异步网络请求
  • 支持多种数据的解析&序列化格式(Gson、 Json、XML、 Protobuf)
  • 支持对RxJava支持
  • 注解化配置高度解耦、采用大量设计模式简化使用

2.使用方式

大致分成八个步骤:

step1:添加Retrofit库、OkHttp库、数据解析器集成库的依赖,并注册网络权限

在app文件包下的build.gradle中添加依赖,这里用的是JSON数据解析器:

compile 'com.squareup.retrofit2:retrofit:2.4.0'
compile 'com.squareup.okhttp3:okhttp:3.10.0'
compile 'com.squareup.retrofit2:converter-gson:2.4.0'

在AndroidManifest.xml中注册权限:

<uses-permission android:name="android.permission.INTERNET"/>

step2:创建接收服务器返回数据的类

请求后服务器会返回数据,需要根据返回数据的格式和解析方式(Json、XML等)来定义实体类Model。

假设有返回数据格式为如下JSON,其中,如果用户名和密码匹配成功,则code值为1,反之为0:

{
  "code":1,
  "data":{
     "id":10001,
     "username":"Tom",
     "email":"888888888@qq.com",
     "tel":"18088888888"
  },
  "message":"success"
}

则对应的实体类UserInfoModel:

public class UserInfoModel {

    public int code;
    public UserInfo data;
    public String message;
    
    public static class UserInfo{
    
        public int id;
        public String username;
        public String email;
        public String tel;
    }
}

step3:创建用于描述网络请求的接口

定义一个网络请求的接口,接口函数里要定义URL路径请求参数返回类型。其中,需要使用注解来描述请求类型和请求参数。

public interface Interface {
  
    @GET("URL")
    Call<Model>  getCall(@Query("xxx") String xxx);
   
    // 用@GET("URL")声明了URL路径
    // 用getCall()接收网络请求数据,并用注解@Query("xxx") 声明了请求参数
    // 该方法会返回一个Retrofit的Call对象,这里声明了这个对象处理的数据类型为自定义Model
}

在上例中,对应的UserMgrService接口如下,当发送请求参数为Tom和123456时,请求将发送给的URL为『login?username=Tom&pwd=123456』,并会返回之前定义的GSON数据:

public interface UserMgrService{
    
    @GET("login")
    Call<UserInfoModel> login(@Query("username") String username,@Query("pwd") String pwd);
}

常用的注解含义如图:

这里可以发现,@GET和@Query搭配使用,@POST和@Field搭配使用。


step4:创建Retrofit对象并设置数据解析器

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("URL") //设置网络请求的Url地址,注意以要以斜线(代表根目录)结尾
                .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器,这里表示用的是JSON解析返回值
                .build();

常用的数据解析器如图:


step5:生成接口对象

由于是interface不是class,无法直接调用内部方法,需要利用已创建的Retrofit对象去生成代理的接口对象。

UserMgrService service=retrofit.create(UserMgrService.class);

step6:调用接口方法返回Call对象

调用接口对象的方法,返回一个可以执行网络访问的网络工作对象。

Call<UserInfoModel> call=service.login("Tom","123456");

step7:发送网络请求(异步 / 同步)

a.同步:调用Call对象execute(),返回结果是响应体。

//开线程进行网络请求
new Thread(new Runable()){
    @Override
    pubblic void run(){
        Response<UserInfoModel> response=null;
        try{
           response=call.execute();
        }catch{
           e.printStackTrace();
        }
        //处理服务器返回的数据
    }
}.start();

b.异步:调用Call对象enqueue(),参数是一个回调。

//异步时,框架中已经封装好数据转换、线程切换的操作,无需手动开线程
call.enqueue(new CallBack<UserInfoModel>(){
    @Override
    public void onResponse(Call<UserInfoModel> call,Response<UserInfoModel> response){
        //处理服务器返回的数据
    }
    @Override
    public void onFailure(Call<UserInfoModel> call,Throwable t){
    }
});

step8: 处理服务器返回的数据

现在可以去打印出返回结果:

Log.i("response","code:"+response.body().code);//结果为"code:1"

下面给出官方给的simple demo,便于更好的理解Retrofit的使用步骤:

//step3:
public interface GitHub {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
        @Path("owner") String owner,
        @Path("repo") String repo);
  }

  public static void main(String... args) throws IOException {
    // step4:Create a very simple REST adapter which points the GitHub API.
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(API_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    // step5:Create an instance of our GitHub API interface.
    GitHub github = retrofit.create(GitHub.class);

    // step6:Create a call instance for looking up Retrofit contributors.
    Call<List<Contributor>> call = github.contributors("square", "retrofit");

    // step7:Fetch and print a list of the contributors to the library.
    List<Contributor> contributors = call.execute().body();
    
    //step8:
    for (Contributor contributor : contributors) {
      System.out.println(contributor.login + " (" + contributor.contributions + ")");
    } 
  }

实例这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)


以上,可以看到,Retrofit可根据不同的接口定义,灵活地生成对应的网络工作对象,然后利用这个对象去访问网络。它就像一个工厂,只提供产品,本身不处理网络请求,而是让产品去处理网络请求。

图片来源从架构角度看Retrofit的作用、原理和启示

下一篇将进行Retrofit的源码分析~

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 154,661评论 23 678
  • 那天带闺女去杜陵•秦砖汉瓦博物馆玩,正赶上一队团体游客也在里面参观,看样子是一个楼盘组织的活动。博物馆里除了这队人...
    Double_Sun阅读 66评论 0 1
  • 一条母亲河吞噬了很多的生命,我就是曾经被人救下的活口。 时隔二十多年,今天回娘家碰到了我的恩人...
    琴弦封存阅读 52评论 0 0