Retrofit

2020-01-15  本文已影响0人  Liu积土成山

Retrofit用法总结

一.什么是retrofit

retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。

本质过程:App应用程序通过Retrofit请求网络,实质上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由okhttp来完成后续的请求工作。在服务端返回数据后,okhttp将原始数据交给Retrofit,Retrofit根据用户需求解析。

retrofit优点

超级解耦 ,接口定义、接口参数、接口回调不在耦合在一起
可以配置不同的httpClient来实现网络请求,如okhttp、httpclient
支持同步、异步、Rxjava
可以配置不同反序列化工具类来解析不同的数据,如json、xml
请求速度快,使用方便灵活简洁

一.引入依赖

  implementation 'com.squareup.retrofit2:retrofit:2.7.1'
  implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
  implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'

1、请求方法注解

请求方法注解 说明
@GET Get请求
@POST post请求
@PUT put请求
@DELETE delete请求
@PATCH patch请求,该请求是对put请求的补充,用于更新局部资源
@HEAD head请求
@HEAD options请求

2、请求头注解

请求头注解 说明
@Headers 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在
@Header 作为方法的参数传入,用于添加不固定的header,它会更新已有请求头

3、请求参数注解

请求参数注解 说明
@Body 多用于Post请求发送非表达数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据
@Filed 多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数
@FiledMap 多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用
@Part 用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况
@PartMap 用于表单字段,默认接受类型是Map<String,RequestBody>,可用于实现多文件上传
@Path 用于Url中的占位符
@Query 用于Get请求中的参数
@QueryMap 与Query类似,用于不确定表单参数
@Url 指定请求路径

4、请求和响应格式(标记)注解

标记类注解 说明
@FromUrlCoded 表示请求发送编码表单数据,每个键值对需要使用@Filed注解
@Multipart 表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值
@Streaming 表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用

1.0

首先创建我们的接口

public interface API {
    /** 
    * @GET方法      请求方法注解,get请求,括号内的是请求地址,Url的一部分
    * Call<*>       返回类型,*表示接收数据的类,一般自定义
    * getJson       接口方法名称,括号内可以写入参数
    * 这是一个没有网络参数的get请求方式,需要在方法头部添加@GET注解,表示采用get方法访问网络请求,括号 
    * 内的是请求的地址(Url的一部分) ,其中返回类型是Call<*>,*表示接收数据的类,如果想直接获取ResponseBody中的内容,可以定义网络请求返回值为Call<ResponseBody>,ResponseBody是请求网络后返回
    * 的原始数据,如果网络请求没有参数,不用写。因为我这里用postman进行了测试知道返回的具体内容是什么了,
    *所以我创建了个javaBean,名字叫JsonResultBean,如果不知道想看返回的原始数据则使用*Call<ResponseBody> getJson();
    */
    
    @GET("get/text")
    Call<JsonResultBean> getJson();

    
    // 带参数的,如果是参数少可以用@Query请求参数注解
    // "keyword" 参数字段,与后台给的参数保持一致
    // String  声明参数的类型
    
    @GET("/get/param")
    Call<GetWithParamsBean> getWithParams(@Query("keyword") String keyword,
                                          @Query("page") int page,
                                          @Query("order") String order);
                                          
    // 如果参数多可以用QueryMap,请求参数注解,与@Query类似,用于不确定表单参数
    // Map<String, Object> params 通过Map将不确定的参数传入,相当于多个Query参数
    @GET("/get/param")
    Call<GetWithParamsBean> getWithParams(@QueryMap Map<String,Object> params);

    // post
    @POST("/post/string")
    Call<PostWithParamsBean> postWithParams(@Query("string") String content);

    // 没有参数的post方法 @POST请求方法注解,表示采用post方法访问网络请求,括号后面是部分的URL地址 
    @POST
    Call<PostWithParamsBean> postWithUrl(@Url String url);
    
    // post上传表单
    // @FormUrlEncoded  请求格式注解,请求实体是一个From表单,每个键值对需要使用@Field注解
    // @Field 请求参数注解,提交请求的表单字段,必须要添加,而且需要配合@FormUrlEncoded使用
    // "userName" 参数字段,与后台必须保持一致
    // userName password 传进来实际的参数
//Post请求如果有参数需要在头部添加@FormUrlEncoded注解,表示请求实体是一个From表单,每个键值对
//需要使用@Field注解,使用@Field添加参数,这是发送Post请求时,提交请求的表单字段,必须要添加的,
//而且需要配合@FormUrlEncoded使用
    @FormUrlEncoded
    @POST("/login")
    Call<ResponseBody> doLogin(@Field("userName") String userName, @Field("password") String password);

    // post 参数多的时候传递,@FieldMap  请求参数注解,与@Field作用一致,用于不确定表单参数
    // Map<String, Object> map 通过Map将不确定的参数传入,相当于多个Field参数
    @FormUrlEncoded
    @POST("/login")
    Call<ResponseBody> postLoginMap(@FieldMap Map<String,Object> params);

    // postJsonObject 传递对象
    @POST("/post/comment")
    Call<PostWithJsonObjectBean> postJsonObjet(@Body CommentItemBean itemBean);

    // 上传文件,文件可以包括 图片 、 视频、音频 @Part注解,要跟@Multipart注解一起使用
    // 我们可以在方法参数内添加请求头,@Header用于添加不固定的请求头,作用于方法的参数,作为方法的
    // 参数传入,该注解会更新已有的请求头。header用于添加不固定的请求头,headers用于添加固定的请求头
    // @Multipart 表示请求实体是一个支持文件上传的表单,需要配合@Part和@PartMap使用,适用于文件上传
    // 用于表单字段,适用于文件上传的情况,@Part支持三种类型:RequestBody、MultipartBody.Part、 任意
    // 类型
    // @PartMap用于多文件上传, 与@FieldMap和@QueryMap的使用类似
    @Multipart
    @POST("/api/AppAniImgType/UploadToAliyun")
    Call<FileUploadResult> postFile(@HeaderMap Map<String,Object> headers,@Part MultipartBody.Part file);
    }
    
     /**
      * 多文件上传:通过 List<MultipartBody.Part> 传入多个part实现
      * @param parts 每一个part代表一个文件
      * @return 状态信息String
      */
    @Multipart
    @POST("UploadServerAddr")
    Call<String> uploadFilesMultipartBodyParts(@Part() List<MultipartBody.Part> parts);
    
    // @Streaming表示响应体的数据用流的方式返回,使用于返回数据比较大,该注解在下载大文件时特别有用
    @Streaming
    @POST("gists/public")
    Call<ResponseBody> getStreamingBig();
    

1.1

新建一个单例功我们所有页面使用的网络请求-包含我们的baseUrl

public class RetrofitManager {
    // 我们的baseUrl
    public static String BASE_URL="http://xxxxx/";

    //设置超时时间
    public static final int CONNECT_TIME_OUT = 100000;
    private static RetrofitManager sRetrofitManager = null;
    private Retrofit mRetrofit;

    private RetrofitManager() {
        createRetrofit();
    }

    private void createRetrofit() {
        //设置一下okHttp的参数
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)

                .build();
        mRetrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())// 转换器直接转换成了bean类
                .build();
    }

    public static RetrofitManager getInstance() {
        if (sRetrofitManager == null) {
            synchronized (RetrofitManager.class) {
                if (sRetrofitManager == null) {
                    sRetrofitManager = new RetrofitManager();
                }
            }
        }
        return sRetrofitManager;
    }

    public Retrofit getRetrofit() {
        return mRetrofit;
    }

}

二. 在我们的页面中使用

    private API mApi;
    
    在onCreate()方法中调用
    mApi = RetrofitManager.getInstance().getRetrofit().create(API.class);
    
    /*
     * get方法请求网路
     * */
    public void getClickRequest(View view) {
        Call<JsonResultBean> task = mApi.getJson();
        task.enqueue(new Callback<JsonResultBean>() {
            @Override
            public void onResponse(Call<JsonResultBean> call, Response<JsonResultBean> response) {
                Log.i(TAG, "onResponse:----> " + response.code());
                if (response.code() == HttpURLConnection.HTTP_OK) {
                    JsonResultBean resultBean = response.body();
                    updateList(resultBean);
                }
            }

            @Override
            public void onFailure(Call<JsonResultBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /**
     * 带参数的请求
     */
    public void getClickParams(View view) {
        Call<GetWithParamsBean> task = mApi.getWithParams("大家好", 10, "10");
        task.enqueue(new Callback<GetWithParamsBean>() {
            @Override
            public void onResponse(Call<GetWithParamsBean> call, Response<GetWithParamsBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (response.code() == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<GetWithParamsBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /**
     * 带参数的用QueryMap
     */
    public void getClickParamsQueryMap(View view) {
        Map<String, Object> params = new HashMap<>();
        params.put("keyword", "搜索关键字");
        params.put("page", 10);
        params.put("order", "0");
        Call<GetWithParamsBean> task = mApi.getWithParams(params);
        task.enqueue(new Callback<GetWithParamsBean>() {
            @Override
            public void onResponse(Call<GetWithParamsBean> call, Response<GetWithParamsBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (response.code() == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<GetWithParamsBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /**
     * post
     */
    public void postClickParamsQuery(View view) {
        Call<PostWithParamsBean> task = mApi.postWithParams("测试内容");
        task.enqueue(new Callback<PostWithParamsBean>() {
            @Override
            public void onResponse(Call<PostWithParamsBean> call, Response<PostWithParamsBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (response.code() == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());

                }
            }

            @Override
            public void onFailure(Call<PostWithParamsBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /*
     * postUrl
     * */
    public void postWithUrl(View view) {
        // 参数是 string
        String url = "/post/string?string=测试内容";
        Call<PostWithParamsBean> task = mApi.postWithUrl(url);
        task.enqueue(new Callback<PostWithParamsBean>() {
            @Override
            public void onResponse(Call<PostWithParamsBean> call, Response<PostWithParamsBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (response.code() == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());

                }
            }

            @Override
            public void onFailure(Call<PostWithParamsBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });

    }

    /*
     * post请求,body携带字符串内容(json)
     * */
    public void postJsonObject(View view) {
        CommentItemBean itemBean = new CommentItemBean();
        itemBean.setArticleId("123456");
        itemBean.setCommentContent("这是我提交测试的评论内容...");
        // PostWithJsonObjectBean 也可以通过对象形式拿返回值
        Call<PostWithJsonObjectBean> task = mApi.postJsonObjet(itemBean);
        task.enqueue(new Callback<PostWithJsonObjectBean>() {
            @Override
            public void onResponse(Call<PostWithJsonObjectBean> call, Response<PostWithJsonObjectBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<PostWithJsonObjectBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /*
     * 拦截器的使用
     * */
    public void postJsonObject2(View view) {
        CommentItemBean itemBean = new CommentItemBean();
        itemBean.setArticleId("123456");
        itemBean.setCommentContent("这是我提交测试...");

        OkHttpClient.Builder okhttpClient = new OkHttpClient.Builder();
        HttpLoggingInterceptor looger = new HttpLoggingInterceptor();
        looger.setLevel(HttpLoggingInterceptor.Level.BODY);
        // 只在开发版本中才会记录
        if (BuildConfig.DEBUG) {
            okhttpClient.addInterceptor(looger);
        }
        okhttpClient.addInterceptor(looger);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RetrofitManager.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())// 转换器直接转换成了bean类
                .client(okhttpClient.build())
                .build();
        API service = retrofit.create(API.class);
        Call<PostWithJsonObjectBean> call = service.postJsonObjet(itemBean);
        call.enqueue(new Callback<PostWithJsonObjectBean>() {
            @Override
            public void onResponse(Call<PostWithJsonObjectBean> call, Response<PostWithJsonObjectBean> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<PostWithJsonObjectBean> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });

    }

    /*
     * 登录 提交表单
     * */
    public void clickLogin(View view) {
        Call<ResponseBody> call = mApi.doLogin("admin","123456");
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call,Response<ResponseBody> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }
    /*
    * 提交表单 map 多参数形式
    * */
    public void postLoginMap(View view){
        HashMap<String,Object> map = new HashMap<>();
        map.put("admin","张三");
        map.put("password","123456");
        Call<ResponseBody> call = mApi.postLoginMap(map);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });
    }

    /*
     * post file 上传文件 文件包括 图片 视频 音频等等
     * @Part注解,要跟@Multipart注解一起使用。
     * */
    public void postFile(View view) {
//              String path = Environment.getExternalStorageDirectory() + File.separator + "20191220_113301.jpg";
        //创建文件,这里演示图片上传
        File file = new File("/storage/emulated/0/Download/1.jpg");
        if (!file.exists()) {
            file.mkdir();
        }
        //声明类型,这里是传的图片
        MediaType mediaType = MediaType.parse("image/*");
        //将文件转化为RequestBody对象
        //需要在表单中进行文件上传时,就需要使用该格式:multipart/form-data
        RequestBody fileBody = RequestBody.create(mediaType, file);
        // MultipartBody.Part  和后端约定好Key,这里的partName是用file
        // 将文件转化为MultipartBody.Part
        //第一个参数:上传文件的key;第二个参数:文件名;第三个参数:RequestBody对象
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
        // 添加描述
//        String descriptionString = "hello, 这是文件描述";
//        RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("authToken", "08c958df-187f-4e11-973b-3495a8e8e0ae");
        hashMap.put("appKey", "6f9f7cfd-a92d-45a0-8e4a-d2aa96b84b27");
        Call<FileUploadResult> task = mApi.postFile(hashMap, part);
        task.enqueue(new Callback<FileUploadResult>() {
            @Override
            public void onResponse(Call<FileUploadResult> call, Response<FileUploadResult> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<FileUploadResult> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });

    }
    /*
    * 多文件上传
    * */
    public void partMapDataCall(View view) {
        ArrayList<File> list = new ArrayList<>();
        list.add(new File("/sdcard/0/test0.jpg"));
        list.add(new File("/sdcard/0/test1.jpg"));

        List<MultipartBody.Part> parts = new ArrayList<>(list.size());
        for(File file : list) {
            RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
            MultipartBody.Part part = MultipartBody.Part.createFormData("image", file.getName(), requestBody);
            parts.add(part);
        }
        Call<String> call = mApi.uploadFilesMultipartBodyParts(parts);
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                int code = response.code();
                Log.i(TAG, "onResponse:----> " + code);
                if (code == HttpURLConnection.HTTP_OK) {
                    Log.i(TAG, "onResponse:---->" + response.body());
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.i(TAG, "onFailure: ---->" + t.toString());
            }
        });

    }
上一篇 下一篇

猜你喜欢

热点阅读