Retrofit+okhttp3使用,附带源码解析

一:认识Retrofit和okhttp3

Retrofit是由square 开发设计的 网络请求框架

官方网址:Retrofit

Okhttp 是由square 开发设计的 网络请求库,请求/响应API采用流畅的构建器和不变性设计。它同时支持同步阻塞调用和带有回调的异步调用

官方网址:Overview - OkHttp

这篇博客是网络请求的基础篇,使用Retrofit作为网络请求及响应的载体,了解Retrofit的注解,Okhttp的作用在于日志过滤,以及完善网络请求(比如超时处理,请求体处理等)

使用方法如下:

在app\build.gradle

1:依赖Maven库

dependencies {
    //retrofit2 okhttp3
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
}

2:jar包依赖

     在官网下载

二:准备工作

免费的Json数据接口 :

1:构造Retrofit对象

        //构造retrofit,返回请求接口
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .client(builder.build())
                .build();
        service =  retrofit.create(BaseService.class);

2:添加okhttp日志过滤器

        //构造okhttp3,日志过滤
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT);
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(BuildConfig.DEBUG){
            builder.addInterceptor(interceptor);
        }

3:构建CallBack

    //构建Callback
    public void callEnqueue(Call<T> call,BaseListener<T> listener){
        call.enqueue(new Callback<T>() {
            @Override
            public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {
                if(response.isSuccessful()){
                    listener.onResponse(response.body());
                }else{
                    listener.onFail(response.message());
                }
            }

            @Override
            public void onFailure(@NonNull Call<T> call, @NonNull Throwable t) {
                listener.onFail(t.getMessage());
            }
        });
    }

4:完善Service请求接口,了解各注解作用

//方法注解:@GET  @POST  @PUT  @DELETE  @PATH  @HEAD  @OPTIONS  @HTTP
//
//标记注解:@FormUrlEncoded  @Multipart   @Streaming
//
//参数注解:@Query  @QueryMap  @Body  @Field  @FieldMap  @Part  @PartMap
//
//其他注解:@Path  @Header  @Headers  @Url

 以GET/POST/包含请求头Headers,路径参数,请求参数,Json数据,文件参数为例

    //路径参数
    @GET("posts/{postId}/comments")
    Call<List<CommentsBean>> getComments(
            @Path("postId") int postId
    );

    @GET("photos")
    Call<List<PhotoBean>> getPhoto(
            @Query("id") int id
    );

    //请求参数
    @GET("users")
    Call<List<UserBean>> getUser(
            @Query("id") int id);

    //Post请求
    @POST("todos")
    Call<TodoBean>postTodo();

    //包含请求头的POST请求
    @Headers("Content-Type:application/x-www-form-urlencoded")
    @POST("api/sdk/stat/v1/launch/{gameId}/{channelId}")
    Call<StatsBean>postLaunchGame(
          @Path("gameId") String gameId,
          @Path("channelId") String channelId,
          @Body RequestBody responseBody
    );

    //包含json的POST请求
    //上传跑步数据
    @FormUrlEncoded
    @POST("Record/uploadRunningRecord")
    Call<BaseBean> uploadRunningRecord(@Field("Json") String route);

    //上传跑步地图截屏
    @Multipart
    @POST("Record/uploadRunningImage")
    Call<BaseBean> uploadRunningImage(@Part MultipartBody.Part file,
                                      @Query("sessionId") String sessionId,
                                      @Query("studentId") String studentId);

5:发起请求,调用实例

    private void getPhoto(ImageView imageView) {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("正在加载中...");
        dialog.show();
        BaseModel<List<PhotoBean>> model = new BaseModel<>();
        Call<List<PhotoBean>> call = model.service.getPhoto(3);
        model.callEnqueue(call, new BaseListener<List<PhotoBean>>() {
            @Override
            public void onResponse(List<PhotoBean> bean) {
                dialog.dismiss();
                Glide.with(MainActivity.this).load(bean.get(0).getUrl())
                        .placeholder(R.drawable.ic_launcher_background)
                        .into(imageView);
            }

            @Override
            public void onFail(String e) {
                dialog.dismiss();
                Log.d(TAG, "getPhoto onFail:" + e);
            }
        });
    }

RetrofitonResponseonFail是在主线程的,已经完成了线程切换,可以进行UI操作。

这是与Okhttp的区别。

6:效果图

附上完整demo:

GitHub - sunbofly23/JavaRetrofitOkhttp: retrofit+okhttp,安卓网络请求框架

三:从源码分析:

基于retrofit:2.9.0

下面简单梳理了一下retrofit 使用的技术点

retrofit:构建者设计模式,工厂模式,反射,动态代理,类加载器,注解

这里先过一遍retrofit从构建,到与okhttp转换的流程:

Retrofit.

->create(Retrofit.java)

->invokeHandle(Retrofit.java)

->loadServiceMethod-一层缓存(serviceMethodCache)(ServiceMethod.java)

->createCallAdapter(HttpServiceMethod.java)

->createResponseConverter(HttpServiceMethod.java)

->invoke(HttpServiceMethod.java)

->构造OkHttpCall并且adapt(call) 这一步结束,就是将Call交给okhttp发起请求

->get(CallAdapter<R, T> .Factory.java)

->DefaultCallAdapterFactory(DefaultCallAdapterFactory extends CallAdapter.Factory)

->ExecutorCallbackCall(DefaultCallAdapterFactory.java)这一步完成线程的切换

->CompletableFutureCallAdapterFactory(CompletableFutureCallAdapterFactory extends CallAdapter.Factory)

->retrun future(CompletableFuture)

然后从Retrofit.create开始分析 

->loadServiceMethod

 ->createCallAdapter、createResponseConverter

 ->invoke

 ->DefaultCallAdapterFactory

 ->ExecutorCallbackCall

 这里就会将请求 进队列交给okhttp3

 ->CompletableFutureCallAdapterFactory

 ->retrun future/callback.onResponse解析response.body()

四:总结

复盘网路请求Retrofit+okhttp的简单使用,据了解,最新技术

Retrofit+okhttp+moshi+kotlin协程

可实现的网络请求框架更易扩展,健壮。后续还要学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunbofiy23

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值