Android开发 retrofit入门讲解

Posted 观心静

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发 retrofit入门讲解相关的知识,希望对你有一定的参考价值。

前言

  retrofit基于okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.如果你不了解OKhttp建议你还是先了解它在来学习使用retrofit,传送门:Android 开发 框架系列 OkHttp使用详解

  Retrofit优势,就是简洁易用,解耦,扩展性强,可搭配多种Json解析框架(例如Gson),另外还支持RxJava.但是,这篇博客不讲解RxJava配合使用的部分,与RxJava的配合使用将在另外一篇博客中讲解.

  另外retrofit已经是封装的非常好了,作者的想的很完整,它的封装的思想十分准确而且恰到好处(堪称标准),所以不建议多此一举的再次封装retrofit. 再次封装不会让你很牛逼. 只会让你看起来更蠢。你会想封装只能说明你压根没理解或者阅读过retrofit。过度封装以后出现一个任何问题都可能出现重构灾难,那就整个项目的接口代码都要增加代码。减少重复工作只需要给2个东西做一个工具类(OkHttpClient与Retrofit.Builder()),在一些简单场景只需要将配置好的网络接口列表服务类保存好(保存到Application或者单例保存)。

Github地址

  https://github.com/square/retrofit

依赖

  如果你不需要使用RxJava模式,那么你只需要依赖下面2个:

    implementation \'com.squareup.retrofit2:retrofit:2.6.2\'
    implementation \'com.squareup.retrofit2:converter-gson:2.4.0\'

  gson是用来解析的Json数据使用的(个人偏爱Gson),retrofit也支持其他解析工具比如fastJson

简单的Demo(异步请求)

  老规矩按思维顺序讲解demo

1.创建Retrofit请求基础配置

  Retrofit配置好后,你可以将它单例保存,也不可以保存。Retrofit.Builder()就是希望你根据不同的业务创建出不同的Retrofit来搭配接口服务使用。

  private Retrofit mRetrofit;
  private void initHttpBase(){
        mRetrofit = new Retrofit.Builder()
                .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的网络地址  baseUrl不能为空,且强制要求必需以 / 斜杠结尾
                .addConverterFactory(GsonConverterFactory.create())//使用Gson解析
          .callbackExecutor(Executors.newSingleThreadExecutor())//使用单独的线程处理 (这很重要,一般网络请求如果不设置可能不会报错,但是如果是下载文件就会报错)
                .build();
    } 

注意! base的网络地址 baseUrl不能为空,且强制要求必需以 / 斜杠结尾

2.创建数据返回后的Bean类

public class LoginBean {
    private int code;
    private String message;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2.创建一个网络请求接口

public interface HttpList {

    @FormUrlEncoded //注解表示from表单  还有@Multipart 表单可供使用 当然你也可以不添加
    @POST("test/login_test") //网络请求路径
    Call<LoginBean> login(@Field("number") String number, @Field("password") String password); //@Field("number") 为post值的的key

}

注意,这是一个接口类. LoginBean则是数据返回后的Bean类(Retrofit会自动使用导入的Gson解析)

注意! @POST("test/login_test") 这路径最前面不能加斜杠 /  ,否则它会自动裁剪路径,这样会导致你的路径错误

3.请求网络

这里的mRetrofit.create创建的接口服务,如果无改变Retrofit,也可以用一个单例类保存在Application起来全局使用。

private void postHttp(){
        HttpList httpList = mRetrofit.create(HttpList.class);
        Call<LoginBean> call = httpList.login("181234123", "123456");
        call.enqueue(new Callback<LoginBean>() {
            @Override
            public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
                LoginBean bean = response.body();
                Log.e(TAG, "onResponse: code="+bean.getCode());
                Log.e(TAG, "onResponse: message="+bean.getMessage());
            }

            @Override
            public void onFailure(Call<LoginBean> call, Throwable t) {
                Log.e(TAG, "onFailure: 网络请求失败="+t.getMessage());

            }
        });
    }

 这样,我们就完成了一个网络请求.是不是特别简单

同步请求

private void postHttp2() {
        HttpList httpList = mRetrofit.create(HttpList.class);
        final Call<LoginBean> call = httpList.login("181234123", "123456");
        new Thread(new Runnable() { //android主线程不能操作网络请求,所以new一个线程来操作
            @Override
            public void run() {
                try {
                    Response<LoginBean> response = call.execute();//同步请求网络
                    LoginBean bean = response.body();
                    Log.e(TAG, "onResponse: code=" + bean.getCode());
                    Log.e(TAG, "onResponse: message=" + bean.getMessage());
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }

取消网络请求

    public void cancelHttp(){
        HttpList httpList = mRetrofit.create(HttpList.class);
        //这里贴这部分代码是告诉call是哪里来的,关键点就是这个call,当然你也可以从回调里获取
        mCall = httpList.login("181234123", "123456");

        mCall.cancel(); //取消请求
    }

如何添加Header头

以固定数据的形式添加头信息

public interface HttpList {

    @Headers({"content1:one","content2:two"})
    @POST("test/logout_test")
    Call<LoginBean> logout1();

}

以非固定数据的形式添加头信息

public interface HttpList {

    @POST("test/logout_test")
    Call<LoginBean> logout2(@Header("content") String content);

}

Body配置

Body一般有4个种类

  • application/x-www-form-urlencoded 表单数据
  • multipart/form-data 表单文件上传
  • application/json 序列化JSON数据
  • text/xml XML数据

框架直接提供的2个Body

public interface HttpList {

    @FormUrlEncoded //application/x-www-form-urlencoded  表单body
    @POST("test/login_test") 
    Call<LoginBean> login2(@Field("number") String number, @Field("password") String password);


    @Multipart //multipart/form-data  此body支持文件上传与下载
    @POST("test/login_test") 
    Call<LoginBean> login3(@Field("number") String number, @Field("password") String password);


}

自定义Body

其他2个就需要自定义创建了,下面举例Json Body的创建:

  /**
     *
     * @param string  直接导入需要发送给服务器的JSON的String值
     * @return
     */
    public static RequestBody getRequestBody(String string) {
        return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), string);
    }

在接口类参数需要设置为 @Body RequestBody requestBody

    @POST("app/system/demo")
    Observable<UpdateInfo> demo(@Body RequestBody requestBody);

手动解析Response请求返回

有时候我们不需要使用GsonConverterFactory帮我们解析body数据,我们希望自己能操作数据并且解析。比如获取下载数据的流,我们需要使用ResponseBody类(这个类是okhttp返回body类)。代码如下

public interface HttpList {

    @GET("aaa/bbb/ccc/")
    Call<ResponseBody> post(@Query("token") String token);
}

 

请求后返回的ResponseBody使用方式请参考okhttp的博客 https://www.cnblogs.com/guanxinjing/p/9708575.html

添加配置的OkHttpClient(主要使用请求超时/拦截器等功能)

上面说了retrofit是基于Okhttp开发的网络请求框架,所以它有一部分的功能依然需要使用Okhttp的方式来配置比如请求超时时间/设置拦截器等等,下面就展示一下如何添加

    private void initHttpBase2() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(false) //在连接失败时重试
                .callTimeout(30, TimeUnit.SECONDS) //呼叫超时,设置此参数为整体流程请求的超时时间
                .connectTimeout(20,TimeUnit.SECONDS)//连接超时
                .readTimeout(20,TimeUnit.SECONDS)//读取超时
                .writeTimeout(20,TimeUnit.SECONDS)//写入超时
//                .callTimeout()//呼叫超时,设置此参数为整体流程请求的超时时间
//                .addInterceptor() //设置拦截器
//                .authenticator() //设置认证器
//                .proxy()//设置代理
                .build();

        mRetrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的网络地址
                .addConverterFactory(GsonConverterFactory.create())//使用Gson解析
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
    }

部分路径动态的BaseUrl

    @POST("/article/query/{page}/json")
    @FormUrlEncoded
    Observable<DataResponse<Article>> getSearchArticles(@Path("page") int page, @Field("k") String k);

实现Url路径传参数

@Query 有值的查询名称

    @GET("app/data")
    Call<Result> getData(@Query("id") String id);
    @GET("app/data")
    Call<Result> getData(@Query("id") String... id);

@QueryName 只有值没有key的传参

    @GET("app/data")
    Call<Resul> getData(@QueryName String id);
    @GET("app/data")
    Call<Resul> getData(@QueryName String... id);

@QueryMap 用哈希集合传值

    @GET("app/data")
    Call<Result> getData(@QueryMap Map<String,String> map);

 

end

Response

以上是关于Android开发 retrofit入门讲解的主要内容,如果未能解决你的问题,请参考以下文章

Android Retrofit 2.0 的详细 使用攻略(含实例讲解)

Android Retrofit 2.0 的详细 使用攻略(含实例讲解)

Carson带你学Android:这是一份详细的 Retrofit使用教程(含实例讲解)

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

Retrofit 从入门封装到源码解析-张旭童-专题视频课程

Android APP开发入门教程