zoukankan      html  css  js  c++  java
  • Android开发 retrofit入门讲解

    前言

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

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

      另外retrofit已经是封装的非常好了,已经最大程度上的匹配各种使用情况,所以不建议多此一举的再次封装retrofit(最多封装retrofit的单例). 再次封装不会看起来很帅也不会让你很牛逼. 只会让你看起来更蠢.把已经很拓展很解耦的实现全部破坏.

    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用来请求网络(所以你可以实现单例以全局使用),当然下面的代码只是demo:

      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.请求网络

    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);

    添加配置的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

  • 相关阅读:
    设计模式-策略模式
    JavaCV开发详解之19:如何开启GPU硬件加速,使用JavaCV进行音视频的硬解码和硬编码(支持intel、amd和nvidia)
    javaCV开发详解之18:音视频转码(音频编解码和视频编解码)
    JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇)
    JavaCV入门指南:帧过滤器(FrameFilter)的原理与应用
    JavaCV入门指南:调用opencv原生API和JavaCV是如何封装了opencv的图像处理操作?
    javaCV开发详解之17:GIF和APNG动态图片推流和录制成视频文件(以gif转mp4和apng转mp4为例)
    javaCV开发详解之16:使用一张图片推流和一张图片录制成视频文件
    JavaCV入门指南:帧录制器/推流器(FrameRecorder)的原理与应用
    JavaCV入门指南:帧抓取器(FrameGrabber)的原理与应用
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/11594249.html
Copyright © 2011-2022 走看看