zoukankan      html  css  js  c++  java
  • Retrofit 2.0基于OKHttp更高效更快的网络框架 以及自定义转换器

    时间关系,本文就 Retrofit 2.0的简单使用 做讲解  至于原理以后有空再去分析

    项目全面、简单、易懂  地址:

    关于Retrofit 2.0的简单使用如下:  https://gitee.com/bimingcong/MyRetrofit

    private void initGet() {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://v.juhe.cn/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            GetService service = retrofit.create(GetService.class);
            final Call<GetBean> call = service.getString3("toutiao", "shehui", "d05b58fa6901ad9bed77a1ef08bd6ccb");
         
    call.enqueue(new Callback<GetBean>() {
                @Override
                public void onResponse(Call<GetBean> call, Response<GetBean> response) {
                    if (response.isSuccessful()) {
                        GetBean = response.body();
                      
                    }
                }
    
                @Override
                public void onFailure(Call<GetBean> call, Throwable t) {
                    
                 
                }
            });
    
        }

     其中的GetService是干嘛的    里边的@query其实可以理解为get请求url  ?后边那一串参数的键值对

    public interface GetService {
        //直接拼接,记得加问号
        @GET("toutiao/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
        Call<GetBean> getString();
    
        //{name}可以最简单的将其理解为路径替换块,用”{}”表示,与注解@path配合使用 ,为了解耦,参数name==toutiao
        @GET("{name}/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
        Call<GetBean> getString2(@Path("name") String name);
    
        //对于@GET来说,参数信息是可以直接放在url中上传的。那么你马上就反应过来了,这一样也存在严重的耦合!
        //于是,就有了@query
        @GET("{name}/index")
        Call<GetBean> getString3(@Path("name") String name, @Query("type") String type
                , @Query("key") String key);
    
        //假设我要在参数中上传10个参数呢?这意味着我要在方法中声明10个@Query参数?当然不是!
        //Retrofit也考虑到了这点,所以针对于复杂的参数上传,为我们准备了@QueryMap
        @GET("{name}/index")
        Call<GetBean> getString4(@Path("name") String name, @QueryMap HashMap<String, String> hashMap);
    
        //一般Get都没有请求体,所以直接获取接口网址即可 Url动态化
        @GET()
        Observable<ResponseBody> getString5(@Url String url);
    
    }

    针对Post请求  其中的@Field 其实可以理解为 post要提交的 参数键值对  其中还有单个文件 以及多个文件的上传

    public interface PostService {
        @FormUrlEncoded
        @POST("toutiao/index")
        Call<PostBean> postString(@Field("type") String type, @Field("key") String key);
    
        // Post表单提交-多个参数-@FieldMa
        @FormUrlEncoded
        @POST("toutiao/index")
        Call<PostBean> postString2(@FieldMap HashMap<String, String> params);
    
        // Post文件提交 ,每个键值对都需要用@Part注解键名字
        //Multipart 支持文件上传
        @Multipart
        @POST("https://pan.baidu.com/disk/home?#/all?vmode=list&path=%2Fas")
        Call<TestBean> postFile(@Part("photo";filename="test.png"") RequestBody body);
    
        @Multipart
        @POST("xxxx")
        Call<TestBean> postFile2(@PartMap HashMap<String, RequestBody> bodyMap, @Field("token") String token);
    
    
    }

    对应的例子如下:

    //当我获取数据成功后要做什么处理
        public interface OnSuccessListener {
            void onSuccess(Object o);
    
            void onFaile();
        }
     //提供一些方法去调用service实体类的方法,RequestBody上传单个文件
        public void uploadFile(RequestBody body, final OnSuccessListener listener) {
            Call<TestBean> call = mService.postFile(body);
            call.enqueue(new Callback<TestBean>() {
                @Override
                public void onResponse(Call<TestBean> call, Response<TestBean> response) {
                    listener.onSuccess(response);
                }
    
                @Override
                public void onFailure(Call<TestBean> call, Throwable t) {
                    listener.onFaile();
                }
            });
    
        }

    转换器:

    至于自定义转换器 就是 下边这个参数

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://v.juhe.cn/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

     比如我们只希望返回数据是String类型,我们需要自定义一个ConverterFactory

    public class StringConverFactory extends Converter.Factory {
        public static StringConverFactory create() {
            return new StringConverFactory();
        }
     
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                                Retrofit retrofit) {
            Log.d("wyz", "读取数据:responseBodyConverter" + type);
            if (type == String.class) {//此处的Type类型 我的理解是一开始Call对象参数定义的返回值类型
                Log.d("wyz", "执行开始");
                return StringResponseBodyConverter.INSTANCE;
            }
            return null;
        }
     
        @Nullable
        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            Log.d("wyz", "请求数据类型:" + type);
            if (type == NetRequest.class){
     
            }
            return null;
        }
    final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
        public static final StringResponseBodyConverter INSTANCE =new StringResponseBodyConverter();
        @Override
        public String convert(ResponseBody value) throws IOException {
            Log.d("wyz", "转换开始:" + value);
            String s = value.string();
            return s;
        }

    最后将 ConvertFactory设置到Retrofit实例中就可以了

    retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(getOkHttpClient())
                    .addConverterFactory(StringConverFactory.create())

    日志:

    最后对于 红色的部分是添加一个自定义的Client 此处主要是对相应级别的日志去拦截

    在retrofit2.0中是没有日志功能的。但是retrofit2.0中依赖OkHttp,所以也就能够通过OkHttp中的interceptor来实现实际的底层的请求和响应日志。在这里我们需要修改上一个retrofit实例,为其自定自定义的OkHttpClient。代码如下:

    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
    httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor(httpLoggingInterceptor)
            .build();
    
    Retrofit retrofit = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .client(okHttpClient)
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    需要添加依赖:

    compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'

    效果:

    更加详细的Demo  可以去我的开源中国里看 https://gitee.com/bimingcong/MyRetrofit

  • 相关阅读:
    lix
    docker-desktop: error during connect
    安装Docker Desktop报错WSL 2 installation is incomplete.
    索引二倒排索引和正排索引
    公众号资料分享
    docker使用物理机gpu运行模型
    使用arthas定位java问题
    pytorch设置gpu
    pytorch模型初始化
    【转】OpenGL图形渲染管线、VBO、VAO、EBO、 TBO概念及用例
  • 原文地址:https://www.cnblogs.com/bimingcong/p/9543708.html
Copyright © 2011-2022 走看看