美文网首页
开源库Retrofit

开源库Retrofit

作者: 30cf443c3643 | 来源:发表于2018-11-06 11:22 被阅读15次

Retrofit是square公司对网络请求okhttp的二次封装,通过注解反射的方式,配置网络请求的参数,支持多种返回数据格式解析,支持同步异步调用。
这是一份很详细的 Retrofit 2.0 使用教程里面很详细的讲了注解,数据解析器,网络请求适配。基础的知识都很容易,标记一些比较容易忽视的内容

@FormUrlEncoded 每个键值对需要用@Filed来注解键名,随后的对象需要提供值。否则会报错
@Multipart表示发送form-encoded的数据(适用于 有文件 上传的场景)


@Multipart
@POST("mobile/upload")
Call<ResponseBody> upload(@Part MultipartBody.Part file);
------------------------------------------------------------------------------------------------------
// 创建 RequestBody,用于封装 请求RequestBody
RequestBody requestFile =
        RequestBody.create(MediaType.parse("image/jpg"), file);
 //  image/jpg是我们要上传的文件类型,你总得告诉别人你传的文件是什么格式的对吧,对应了请求体中的Content-Type: image/jpeg
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
        MultipartBody.Part.createFormData("file", file.getName(), requestFile);
-----------------------------------------------------------------------------------------------------
// 添加描述  Http是只能进行纯文本传输,所以在后来支持文件上传后,新增了一个MIME类型,叫multipart/form-data。
//上传文件时  Content-Type:multipart/form-data;同时有boundary分隔上传的内容
String descriptionString = "hello, 这是文件描述";
RequestBody description =
        RequestBody.create(
                MediaType.parse("multipart/form-data"), descriptionString);

-----------------------------------------------------------------------------------------------------

@Headers
Retrofit提供了两种方式来定义HTTP请求头:静态和动态。
静态通过添加注解的方式

public interface WeatherService {
    @Headers("apikey:b86c2269fe6588bbe3b41924bb2f2da2")
    @GET
    Call<WeatherWrapper> weather(@Url String url, @Query("cityname") String cityName);
}

或者动态添加方法参数的方式

@GET
Call<WeatherWrapper> weather(@HeaderMap Map<String, String> headers, @Url String url, @Query("cityname") String cityName);

添加拦截器

在OkHttp中Interceptors拦截器是一种强大的机制,可以监视,重写和重试Call请求


20170529175638399.png

拦截器分为应用拦截器和网络拦截器

添加日志拦截器

class LoggingInterceptor implements Interceptor {
        @Override
        public Response intercept(Interceptor.Chain chain) throws IOException {
            Request request1 = chain.request();

            long t1 = System.nanoTime();
            Log.d("tag",String.format("Sending request %s on %s%n%s",
                    request1.url(), chain.connection(), request1.headers()));

            Response response = chain.proceed(request1);

            long t2 = System.nanoTime();
            Log.d("tag",String.format("Received response for %s in %.1fms%n%s",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers()));

            return response;
        }
    }

//同时通过配置okhttpclient添加网络拦截器

 OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)//设置超时时间
                .addNetworkInterceptor(new LoggingInterceptor())
                .retryOnConnectionFailure(true);
        OkHttpClient client=builder.build();


        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        mApiService = retrofit.create(ApiService.class);

测试得到结果


2018-11-05_160239.png

同样 可以通过添加拦截器来添加请求头

okHttpClientBuilder.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Request.Builder requestBuilder = original.newBuilder()
                .header("platform", "platform")//平台
                .header("sysVersion", "sysVersion")//系统版本号
                .header("device", "device")//设备信息
                .header("screen", "screen")//屏幕大小
                .header("uuid", "uuid")//设备唯一码
                .header("version", "version")//app版本
                .header("apiVersion", "apiVersion")//api版本
                .header("token", "token")//令牌
                .header("channelId", "channelId")//渠道
                .header("networkType", "networkType");//网络类型
        Request request = requestBuilder.build();
        return chain.proceed(request);
    }
});

还有通过添加缓存拦截器来实现无缓存功能

public class CacheInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!NetUtil.isNetworkConnected()) {//没网强制从缓存读取(必须得写,不然断网状态下,退出应用,或者等待一分钟后,就获取不到缓存)
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
        }
        Response response = chain.proceed(request);
        if (NetUtil.isNetworkConnected()) {//有网情况下,从服务器获取
            int maxAge = BuildConfig.DEFAULT_COOKIE_NETWORK_TIME;
            // 有网络时, 缓存最大保存时长为60s
            response.newBuilder()
                    .header("Cache-Control", "public, max-age=" + maxAge)
                    .removeHeader("Pragma")
                    .build();
        } else {//没网情况下,一律从缓存获取
            // 无网络时,设置超时为30天
            int maxStale = BuildConfig.DEFAULT_COOKIE_NO_NETWORK_TIME;
            response.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .removeHeader("Pragma")
                    .build();
        }
        return response;
    }

CallAdapter

我们知道通过添加RxJavaCallAdapter可以将call类型编程observer类型。那么如何去变成其他类型呢?在Architecture Components的代码中就有例子,将call类型装换成livedata<ApiResponse>的示例,ApiResponse是一个判断网络请求是否成功的类

public class LiveDataCallAdapter<R> implements CallAdapter<R,LiveData<ApiResponse<R>>> {
    private final Type responseType;
    public LiveDataCallAdapter(Type responseType) {
        this.responseType = responseType;
    }
    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public LiveData<ApiResponse<R>> adapt(final Call<R> call) {
        return new LiveData<ApiResponse<R>>() {
            private AtomicBoolean started = new AtomicBoolean(false);//boolean的原子类型
            @Override
            protected void onActive() {
                super.onActive();
                if (started.compareAndSet(false,true)){    //compareAndSet预期arg0跟started是否一致,一致则started赋值为arg1;返回值实际上是是否成功修改
                    call.enqueue(new Callback<R>() {
                        @Override
                        public void onResponse(Call<R> call, Response<R> response) {
                            postValue(new ApiResponse<>(response));
                        }

                        @Override
                        public void onFailure(Call<R> call, Throwable t) {
                            postValue(new ApiResponse<R>(t));
                        }
                    });
                }
            }
        };
    }
}
---------------------------------------------------------------------------------------------------------

public class LiveDataCallAdapterFactory extends CallAdapter.Factory {

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != LiveData.class) {
            return null;
        }
        Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
        Class<?> rawObservableType = getRawType(observableType);
        if (rawObservableType != ApiResponse.class) {
            throw new IllegalArgumentException("type must be a resource");
        }
        if (! (observableType instanceof ParameterizedType)) {
            throw new IllegalArgumentException("resource must be parameterized");
        }
        Type bodyType = getParameterUpperBound(0, (ParameterizedType) observableType);
        return new LiveDataCallAdapter<>(bodyType);
    }
}

相关文章

  • 开源库Retrofit

    Retrofit是square公司对网络请求okhttp的二次封装,通过注解反射的方式,配置网络请求的参数,支持多...

  • 2023-02-03

    框架简介 Lotus 网络库基于 Retrofit 进行封装,Retrofit是Square公司开源的网络框架,底...

  • Android - 网络请求之 Retrofit2 + RxJa

    目录 引用 与其他开源请求库对比 Retrofit注解 使用GET请求POST请求 Retrofit2 + RxJ...

  • retrofit - 收藏集 - 掘金

    Android 网络开源库 - Retrofit(六) 源码浅析 - 上 - Android - 掘金 Retro...

  • Android 开源库之网络请求

    Okhttp OkHttp: 是Square 开源的网络请求库 参考:深入理解OKHttp源码 Retrofit ...

  • Android 网络开源库-Retrofit(一)简单介绍

    �前言 当前的网络开源库有许多,如volley,okhttp,retrofit等,这三个库当前是比较火的,其中,o...

  • Retrofit源码初探

    什么是Retrofit2 Retrofit2 可以说是目前最流行的类型安全网络库,是Square公司的一个开源项目...

  • Retrofit使用入门

    Retrofit是Square开发的一个用于网络请求的开源库,内部封装了okhttp,并且和RxAndroid完美...

  • android 最流行技术开源框架

    腰果除了网络模块使用了Retrofit+RxJava,图片加载模块使用了Glide 腰果使用了以下开源库 Retr...

  • 开源库之 Retrofit 源码分析

    分析一波 Retrofit 的源码实现。 简单使用 官方给出了使用例子,具体详情参看 官网。 如果加入 RxJav...

网友评论

      本文标题:开源库Retrofit

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