美文网首页Android开发Android开发经验谈Android技术知识
Android Retrofit2(一)相关概念和基本使用

Android Retrofit2(一)相关概念和基本使用

作者: 程序员三千_ | 来源:发表于2020-04-21 16:10 被阅读0次

    Retrofit是什么

    retrofit是一个restful的http网络请求框架的封装,但网络请求不是由retrofit来完成的,它只是封装了请求参数、header、url、返回结果等信息,而真正处理网络请求的是由OkHttp来完成的。

    基础使用

    • 1、导包
    //网络请求相关 implementation
    "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
           implementation "com.squareup.retrofit2:retrofit-
    mock:$rootProject.retrofitVersion"
           implementation "com.squareup.retrofit2:converter-
    gson:$rootProject.retrofitVersion"
           implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
           implementation "com.squareup.retrofit2:converter-
    scalars:$rootProject.retrofitVersion"
           implementation "com.squareup.retrofit2:adapter-
    rxjava2:$rootProject.retrofitVersion"
           implementation "com.squareup.retrofit2:converter-
    gson:$rootProject.retrofitVersion"
    
    • 2、定义一个Http API接口类
    
    interface WanAndroidApi {
       @GET("project/tree/json")
        Call<ProjectBean> getProject();
    }
    
    • 3、使用Retrofit类生成WanAndroidApi 接口实现
    Retrofit retrofit = new Retrofit.Builder()//建造者模式 .baseUrl("https://www.wanandroid.com/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            WanAndroidApi wanAndroidApi =
    retrofit.create(WanAndroidApi.class);//代理实例
    
    • 4、发送HTTP请求,返回Response可以同步或者异步处理
    Call<ProjectBean> call = wanAndroidApi.getProject();//获取具体的某个业务 //同步请求
    Response<ProjectBean> response = call.execute();
    ProjectBean projectBean = response.body();
    //异步请求
    call.enqueue(new Callback<ProjectBean>() {
    @Override
                public void onResponse(final Call<ProjectBean> call, final
    Response<ProjectBean> response) {
                    Log.i("Zero","response: " + response.body());
                }
    @Override
                public void onFailure(final Call<ProjectBean> call, final
    Throwable t) {}
    });
    

    我们知道retrofit是通过注解配置请求的,在源码里我们可以看到一共有26个注解,我们最常用的肯定是GET和POST注解了。

    /** Make a GET request. */
    @Documented
    @Target(METHOD)
    @Retention(RUNTIME)
    public @interface GET {
      /**
       * A relative or absolute path, or full URL of the endpoint. This value is optional if the first
       * parameter of the method is annotated with {@link Url @Url}.
       *
       * <p>See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
       * this is resolved against a base URL to create the full endpoint URL.
       */
      String value() default "";
    }
    
    

    在Retrofit中其实是通过注解 + 泛型 + 动态代理来实现的,并且其中使用了非常多的设计模式,具体我们在源码分析的时候再展开讲。我们回到GET注解:1、@Target(METHOD):代表是一个方法;@Target(PARAMETER):代表是一个参数,2、Retention(RUNTIME):并且是在运行期的注解。我们都知道运行期的注解,我们是需要通过反射获取他的内容的。在Retrofit中所有的26个注解都是运行期的注解。Retrofit在运行期的时候会去动态的解析标记上这些注解的内容。例如我们的GET注解,Retrofit在运行期的时候会去动态的解析标记上@GET,然后获取到"project/tree/json"这些值

    interface WanAndroidApi {
       @GET("project/tree/json")
        Call<ProjectBean> getProject();
    }
    
    
    在retrofit中注解可以分成三类:1、请求方法类 2、标志类 3、参数类

    1、请求方法类注解

    image.png
    • 分别对应HTTP的请求方法
    • 接收一个字符串表示接口的path,与baseUrl组成完整的请求Url

    其中我们需要注意的是HTTP注解,它是一个通用注解,可以替换以上所有的注解,其拥有method, path, hasBody三个属性。例如上面的get请求也可以这样写

     @GET("project/tree/json")
       fun getProject(): Call<ProjectBean>
    
     @HTTP(method = "get",path = "project/tree/json",hasBody = false)
       fun getProject(): Call<ResponseBody>
    

    开发过后端接口的小伙伴看到这个肯定会觉得很熟悉,是不是和SpringBoot的写法很像,细心的小伙伴肯定也注意到了,顺带提一嘴,第一种Call里写的是ProjectBean,另外一种Call写了ResponseBody,其实这两种都可以,ResponseBody是更原始的方式,而你写了具体的实体类的话,retrofit会在内部帮你解析成ProjectBean,其实就是在你构建一个retrofit对象的时候.addConverterFactory(GsonConverterFactory.create())添加了这个GSON转化器,当然你觉得自己很牛逼想自己解析的话可以写成ResponseBody。转换器也是retrofit里很好用的东西,例如我们熟悉的GSON转化器,RxJava转化器,都可以在构建retrofit对象的时候添加进去。

    2、参数类注解

    image.png
    • Headers
     //使用 `@Headers`注解设置固定的请求头,不同的请求头不会相互覆盖,即使名字相同。
      @Headers("Cache-Control: max-age=640000")
    @GET("project/list")
    Call<ProjectBean> getMsg1();
    @Headers({ "Accept: application/vnd.github.v3.full+json","User-Agent:
    Retrofit-Sample-App"})
    @GET("project/{username}")
    Call<ProjectBean> getMsg2(@Path("username") String username);
    

    需要注意的是,在Headers注解里,你可以传入多个Vlaue,源码里面是通过String数组接收的。

    • Header
      使用 @Header 注解动态更新请求头,匹配的参数必须提供给 @Header ,若参数值为 null ,这个头会 被省略,否则,会使用参数值的 toString 方法的返回值。
    @GET("project")
    Call<ProjectBean>getProject3(@Header("Authorization")String
       authorization);
    
    • Body
      使用 @Body 注解,指定一个对象作为 request body 。在使用post请求的时候会被用到。
    @POST("project/new")
    Call<ProjectBean> createProject(@Body ProjectBean user);
    
    • Field和FieldMap
     @FormUrlEncoded
        @POST("xxx")
        fun exmaple4(@Field("name") vararg name:String,
                     @Field("array") array: Array<String>,//name=xxx&age=22
                     @FieldMap map: Map<String,String>
                     ): Call<ResponseBody>
    
    • Path
      @GET("project/{id}/list")
        fun exmaple5(@Path("id") id: Int): Call<ResponseBody>
    
    • Query和QueryMap
     //http://www.xxx.xxx?name=sss&age=22
        @GET("xxxx")
        fun search(@Query("name") name: String,
                   @QueryMap map: Map<String,String>): Call<ResponseBody>
    

    Query和QueryMap是非常常用的,用于Get请求中指定参数

    剩下的参数类注解都是用于表单字段的和Form表单请求一起讲。

    3、 标志类注解

    image.png
    • Streaming
      例如我们服务端返回给我们的图片是以流的方法返回的,我们就可以用到Streaming注解,我这里写个伪代码给大家看看Streaming的使用。
      @Streaming
        @GET
        Call<ProjectBean> downloadFile(@Url String fileUrl);
    

    4、上传单个、多个文件

    • 单个文件
    //第一种方法:RequestBody
     @Multipart
        @POST("project/upload")
        fun upload(@Part("file\";filename=\"test.png") file: RequestBody): Call<ResponseBody>
    
           //上传单个文件
            val file = File("")
            val requestBody = RequestBody.create(MediaType.parse("image/png"),file)
    
            val call = wanAndroidApi.upload(requestBody)
    
            call.enqueue(object : Callback<ResponseBody>{
                override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                }
    
                override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                }
    
            })
    
    //第二种方法:MultipartBody.Part
     @Multipart
        @POST("project/upload")
        fun upload2(@Part file: MultipartBody.Part): Call<RequestBody>
    
      val file = File("")
            val requestBody = RequestBody.create(MediaType.parse("image/png"),file)
            val filePart =  MultipartBody.Part.createFormData("上传的key",
                file.name,requestBody)
            val call = wanAndroidApi.upload2(filePart)
            call.execute()//我这里为了演示,其实是要异步的
    
    
    • 多个文件
    //第一种方法:RequestBody
     @Multipart
        @POST("project/upload")
        fun upload3(@PartMap map: Map<String,RequestBody>): Call<RequestBody>
    
     //图片集合
            val files = listOf<File>()
            val map = mutableMapOf<String,RequestBody>()
            files.forEach() {file ->
                val requestBody = RequestBody.create(MediaType.parse("image/png"),file)
                map["file\";filename=\"test.png"] = requestBody
            }
            wanAndroidApi.upload3(map)
    
    //第二种方法:MultipartBody.Part
     @Multipart
        @POST("project/upload")
        fun upload4(@PartMap map: Map<String,MultipartBody.Part>): Call<RequestBody>
    
     val files = listOf<File>()
            val map = mutableMapOf<String,MultipartBody.Part>()
            files.forEachIndexed { index, file ->
                val requestBody = RequestBody.create(MediaType.parse("image/png"),file)
                val part = MultipartBody.Part.createFormData("上传的key${index}",file.name,requestBody)
                map["上传的key${index}"] = part
            }
            wanAndroidApi.upload4(map)
    

    相关文章

      网友评论

        本文标题:Android Retrofit2(一)相关概念和基本使用

        本文链接:https://www.haomeiwen.com/subject/eoeuihtx.html