Android网络篇—Retrofit网络请求框架详解

Android网络篇—Retrofit网络请求框架详解_第1张图片

介绍

配置大于编码
(Retrofit:http请求库 支持java与android)改进地方:以配置代替编码
冠以 Retrofit 这个名字的这个家伙,应该是某某某的 『Plus』 版本了。
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是 Retrofit 来完成的。Retrofit 2.0 开始内置 OkHttp,前者专注于接口的封装,后者专注于网络请求的高效,二者分工协作。

我们来通俗的理解Retrofit,它是一个可以用于Android和java的网络库,使用它可以简化我们网络操作的工作,提高效率和正确率。我们需要牢牢的记住:所有的第三方库能实现的功能,我们使用原生的API只要花时间和精力也能实现,但是可能会出现很多的bug而且会花费较多的时间和精力,而且性能也不一定很好,第三方的库会帮我们封装底层的一些代码,避免我们做重复多余易出错的事情,让我们专注于业务逻辑,所以学习任何一个第三方库都将是简单的,我们不应心生畏惧。

Android网络篇—Retrofit网络请求框架详解_第2张图片

那么,同样的道理,Retrofit是Square公司开源的一个高质量高效率的http库,它将我们自己开发的底层的代码和细节都封装了起来。在没有Retrofit,okHttp等库的时候,我们可能要自己去写put,get,post,delete请求。但有了这些库之后对于这些请求我们就只需要一行代码或者是一个注解。
所有的网络通信,其核心任务只有一个就是:Client端与Server端进行数据的交互和操作。所以Retrofit就将底层的代码都封装起来只是暴露出了我们业务中的数据模型和操作方法。
这样理解之后,我们学习Retrofit就简单明了很多了。应该从以下这几点开始学习:

如何传入我们业务需求的URL以及变量参数
如何将我们业务中从服务器获取的Jason数据封装为与Retrofit向对应的类或者接口
如何使用Retrofit进行get,post,delete,put等操作。
还有就是如何在我们项目中配置Retrofit

Retrofit特性

  1. 将rest API封装为java接口,我们根据业务需求来进行接口的封装,实际开发可能会封装多个不同的java接口以满足业务需求。(注意:这里会用到Retrofit的注解:比如get,post)
  2. 使用Retrofit提供的封装方法将我们的生成我们接口的实现类,这个真的很赞,不用我们自己实现,通过注解Retrofit全部帮我们自动生成好了。
  3. 调用我们实现类对象的接口方法。
    这样写都太抽象了,看一段代码:
    看一个Retrofit的例子
public interface GitHubService {
@GET("users/{user}/repos")
Call> listRepos(@Path("user") String user);

解释:
1. 这里的Rest API是指服务器端的API,一般会暴露get,post方法
2. GitHubService其实是对Rest API的一个映射关系,在实际开发中,我们可以定义:public interface ClientService,里面包含post ,get 方法。
3. 接口中的方法使用了Retrofit的注解,Retrofit这个库给了我们很多注解,下一节详细介绍
4. listRepos这个方法表示:一个get请求获取给定URL的Repo集合。
5. listRepos传入的参数为我们需要get的url的动态部分。
6. 这里的Repo为我们自己定义的java bean的类:Repo.class用于封装获取的Jason数据。//注意:此处Retrofit又帮我们省掉了很多工作,只需要我们自己定义业务对应的实体类,而Jason数据的转换和封装则帮我们封装好了只需我们调用。

第二步Retrofit会帮我们自动生成接口的实现类的实例,代码如下:

Retrofit retrofit = new Retrofit.Builder()  //01:获取Retrofit对象
                                .baseUrl("https://api.github.com/") //02采用链式结构绑定Base url
                                .build();//03执行操作
GitHubService service = retrofit.create(GitHubService.class);//04获取API接口的实现类的实例对象

解释:
这里的 service 就好比我们的快递哥,还是往返的那种哈~
短短的两行代码解决了很多问题
先获取Retrofit对象并绑定基本参数,设置基本配置
一行代码生成API接口的实例对象

第三步:调用接口中定义的业务方法:get post等:

Call> repos = service.listRepos("octocat");

解释:
调用接口实现类实例的方法,获取服务器上的数据解析存在List中。

涨姿势

Retrofit默认是Gson来解析JSON数据,你也可以设置自己的JSON解析器,比如jackson,可以使用以下代码换成别的解析方式:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create()) //使用工厂模式创建Gason的解析器
.build();
GitHubService service = retrofit.create(GitHubService.class);

注解

@Url 替换url
@QueryMap  替换url中查询参数
@Header  替换header
@FieldMap 替换post请求body中参数
@FormUrlEncoded post请求需要加的方法注解
@POST() 标示该方法为post请求
@GET() 标示该方法为get请求

参数类型

1. Query & QueryMap

@GET("/list")
Call list(@Query("page") int page);

Query 其实就是 Url 中 ‘?’ 后面的 key-value,比如:

http://www.println.net/?cate=android

这里的 cate=android 就是一个 Query,而我们在配置它的时候只需要在接口方法中增加一个参数,即可:

nterface PrintlnServer{    
   @GET("/")    
   Call<String> cate(@Query("cate") String cate);
}

这时候你肯定想,如果我有很多个 Query,这么一个个写岂不是很累?而且根据不同的情况,有些字段可能不传,这与方法的参数要求显然也不相符。于是,打群架版本的 QueryMap 横空出世了,使用方法很简单,我就不多说了。
2. Field & FieldMap
其实我们用 POST 的场景相对较多,绝大多数的服务端接口都需要做加密、鉴权和校验,GET 显然不能很好的满足这个需求。使用 POST 提交表单的场景就更是刚需了,怎么提呢?

 @FormUrlEncoded
   @POST("/")   
   Call example(
       @Field("name") String name,
       @Field("occupation") String occupation);

其实也很简单,我们只需要定义上面的接口就可以了,我们用 Field 声明了表单的项,这样提交表单就跟普通的函数调用一样简单直接了。

等等,你说你的表单项不确定个数?还是说有很多项你懒得写?Field 同样有个打群架的版本——FieldMap,赶紧试试吧~~

3. Part & PartMap
这个是用来上传文件的。话说当年用 HttpClient 上传个文件老费劲了,一会儿编码不对,一会儿参数错误(也怪那时段位太低吧TT)。。。可是现在不同了,自从有了 Retrofit,妈妈再也不用担心文件上传费劲了~~~

public interface FileUploadService {  
    @Multipart
    @POST("upload")    
Call upload(@Part("description") RequestBody description,
                              @Part MultipartBody.Part file);
}

Demo栗子

get请求
依赖

//依赖retrofit的http请求代码
compile 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit
//依赖gson库进行json到javaBean的转换
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//gson

权限

//配置权限 INTERNET
<uses-permission android:name="android.permission.INTERNET"/>

初始化框架
AlertDialog.Builder setTitle与 Retrofit.Builder比较 前者 快速创建对话 后者 快速初始化retrofit框架

  String baseUrl="http://127.0.0.1:8090/";//retrofit要求以/结束,否则会产生错误
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)//设置项目路径 其它路径都改成相对路径 与ApiUrls   HOST    HOME=HOST+"/home"/
                .addConverterFactory(GsonConverterFactory.create(new Gson()))//convert就是将json解析成javaBean
                .build();//执行创建方法

调用retrofit框架去读到一个接口
使用GsonFormat插件获取json对应的javaBean

public class HomeData {

    public List list;
    public List picture;

    public static class AppItem {
        public String des;
        public String downloadUrl;
        public String iconUrl;
        public String id;
        public String name;
        public String packageName;
        public int size;
        public float stars;
    }
}

配置大于编码


public interface GoogleMarketApi {
    //http://127.0.0.1:8090/home?index=0
    //注解@GET:指定求方式 与请求路径
    //@Query是用来设置GET 请求参数变量名
    //返回值泛型是用来指定new Gson().fromJson(json,clz)
    //指定Call 该方法就可以运行子线程,代表异步请求
    @GET("home")
    Call getHomeData(
                  @Query("index")
                  String index);

    //@QueryMap指定map集合为get请求参数
    @GET("home")
    Call getHomeData(
            @QueryMap
            HashMap map);

调用框架读取参数

        //调用retrofit框架去读到一个请求需要的全部参数,参数都是注解或者泛型来标注
        GoogleMarketApi googleMarketApi = retrofit.create(GoogleMarketApi.class);//读取请求方式 请求页面 返回参数
        //可以获取一个异步方法
        //Call method = googleMarketApi.getHomeData("0");

        HashMap<String, String> map=new HashMap<>();
        map.put("index","0");
        Call<HomeData> method = googleMarketApi.getHomeData(map);
        //2.4.执行子线程,处理服务端返回数据 都是将数据传给回调对象(空方法,给开发者编写业务逻辑,注意条件)
        Callback<HomeData> callback=new Callback<HomeData>() {
            //2.4.1.处理请求成功的业务逻辑
            @Override
            public void onResponse(Call<HomeData> call, Response<HomeData> response) {
                //2.4.2.从响应里面获取解析后的javaBean
                HomeData data = response.body();
                if (data != null) {
                    textView.setText(data.list.size()+"");
                }
            }
            //2.4.3.处理请求失败的业务逻辑
            @Override
            public void onFailure(Call<HomeData> call, Throwable t) {
                t.printStackTrace();
                textView.setText(t.getMessage());
            }
        };
        method.enqueue(callback);

Post请求
使用GsonFormat获取json对应的javaBean

public class LoginData {
    /**
     * msg : 成功收到信息
     * data : 5c4c620c-6951-4bc3-bc98-01fc6c096a2e
     */
    public String msg;
    public String data;
}
public interface GoogleMarketApi {
    //http://127.0.0.1:8090/home?index=0
    //注解@GET:指定求方式 与请求路径
    //@Query是用来设置GET 请求参数变量名
    //返回值泛型是用来指定new Gson().fromJson(json,clz)
    //指定Call 该方法就可以运行子线程,代表异步请求
    @GET("home")
    Call getHomeData(
                  @Query("index")
                  String index);

    //@QueryMap指定map集合为get请求参数
    @GET("home")
    Call getHomeData(
            @QueryMap
            HashMap map);


    //http://192.168.79.28:8080/webapi/post?username=itheima&password=123
    //@POST标注当前方法 使用POST请求
    //@Field用来标注post请求参数名
    //@FormUrlEncoded与@Post配合使用,要求对post的参数进行网络编码
    @FormUrlEncoded
    @POST("post")
    Call login(@Field("username")String username,@Field("password") String pwd);
//    @FieldMap用来标注map为Post请求的参数
    @FormUrlEncoded
    @POST("post")
    Call login(@FieldMap HashMap params);
}

开始使用retrofit发送请求

 //初始化框架 AlertDialog.Builder setTitle与Retrofit.Builder比较前者快速创建对话后者快速初始化retrofit框架
        String baseUrl="http://192.168.79.28:8080/webapi/";//retrofit要求以/结束,否则会产生错误
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)//设置项目路径 其它路径都改成相对路径 与ApiUrls   HOST    HOME=HOST+"/home"/
                .addConverterFactory(GsonConverterFactory.create(new Gson()))//convert就是将json解析成javaBean
                .build();//执行创建方法

        //调用retrofit框架去读到一个请求需要的全部参数,参数都是注解或者泛型来标注
        GoogleMarketApi googleMarketApi = retrofit.create(GoogleMarketApi.class);//读取请求方式 请求页面 返回参数

        //可以获取一个异步方法
       // Call method = googleMarketApi.login("itheima", "123");


        HashMap<String, String> params=new HashMap<>();
        params.put("username","itheima");
        params.put("password","123");
        Call<LoginData> method = googleMarketApi.login(params);

        //执行子线程,处理服务端返回数据 都是将数据传给回调对象(空方法,给开发者编写业务逻辑,注意条件)
        Callback<LoginData> callback=new Callback<LoginData>() {
            //处理请求成功的业务逻辑
            @Override
            public void onResponse(Call<LoginData> call, Response<LoginData> response) {
                //从响应里面获取解析后的javaBean
                LoginData data = response.body();
                if (data != null) {
                    textView.setText(data.data);
                }
            }
            //处理请求失败的业务逻辑
            @Override
            public void onFailure(Call<LoginData> call, Throwable t) {
                t.printStackTrace();
                textView.setText(t.getMessage());
            }
        };
        method.enqueue(callback);


    }

参考资料

腾讯Bugly

你可能感兴趣的:(Android-联网工具)