Android 网络申请之Retrofit

一:前言
Retrofit是一个RESTful的HTTP网络申请框架的封装,网络申请的工作实质上是OKHttp实现,而Retrofit仅负责网络申请接口的封装
Retrofit2简略的说就是一个网络申请的适配器,它将一个根本的Java接口通过动静代理的形式翻译成一个HTTP申请,并通过OkHttp去发送申请。此外它还具备弱小的可扩展性,反对各种格局转换以及RxJava
增加依赖:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

前面两个是rxJava反对依赖,以及数据解析器
二:应用
第一步:创立用于形容网络申请的接口
Retrofit将 Http申请 形象成 Java接口:采纳 注解 形容网络申请参数 和配置网络申请参数

public interface ApiService {    @GET("users/{user}/repos")    Call<List<Repo>> listRepos(@Path("user") String user);//@Path传递的是网络申请参数,替换门路{user}下的内容    //比方你配置一个根门路是:http://myhost.com/    这种等价于:GET: http://myhost.com/users/tom/repos        // 获取工作,上面这个是Retrofit+RXJAVA观察者模式的实现    @POST("task/apply")    Observable<BaseBean<GetTaskBean>> getTask(@Body RequestTaskBean requestTaskBean);    }

第二步创立Retrofit实例

Retrofit retrofit =                new Retrofit.Builder()                        .client(okHttpClientBuilder.build())                        .addConverterFactory(GsonConverterFactory.create())//设置数据解析器                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//RXJAVA的适配器工厂                        .baseUrl(HttpConfig.BASE_URL)//设置网络申请的url地址                        .build();

第三步:创立申请接口的实例

  // 创立 网络申请接口 的实例        ApiService  request = retrofit.create(ApiService .class);

第四步:发送申请,同步申请和异步申请

 //对 发送申请 进行封装        Call<List<Repo>> call = request.listRepos("tom");        call.enqueue(new Callback<List<Repo>>() {            //申请胜利时回调            @Override            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {                //申请解决,输入后果                response.body().show();            }            //申请失败时候的回调            @Override            public void onFailure(Call<List<Repo>> call, Throwable throwable) {                System.out.println("连贯失败");            }        });          //同步申请        try {            Response<List<Repo>> response = call.execute();            response.body().show();        } catch (IOException e) {            e.printStackTrace();        }

下面就是一个Retrofit应用的形式

三:Retrofit注解
1.注解类型:网络申请办法

注解代码申请格局
@GETGET申请
@POSTPOST申请
@DELETEDELETE申请
@HEADHEAD申请
@OPTIONSOPTIONS申请
@PATCHPATCH申请
@PUTPUT申请
@DELETEDELETE申请

下面对应的是http的申请形式,DELETE申请:申请服务器删除Request-URI所标识的资源。PUT申请:向指定资源地位上传其最新内容。TRACE申请:回显服务器收到的申请,次要用于测试或诊断。
例如:

@GET("group/{id}/users")Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort); //比方你配置一个根门路是:http://myhost.com/ //下面就相当于:http://myhost.com/group/1/users?sort=mysort  @POST("users/new")Call<User> createUser(@Body User user);

2.注解类型:标记类
我的项目中的申请头Content-Type的值为 multipart/form-data,这是一种十分常见的 POST 数据提交的形式,咱们在应用表单上传文件时就须要应用到这种形式。那我的我的项目申请里不须要上传文件啊,只是简略的键值对表单申请

注解代码标记类
@FormUrlEncoded申请头的Content-Type是application/x-www-form-urlencoded
@Multipart申请头的Content-Type是multipart/form-data
@Streaming申请头的Content-Type
@Multipart@POST("Sys/getVersion")Observable<JsonObject> getNewVersion(@PartMap Map<String, RequestBody> versionBody);//通过学习Retrofit2的注解阐明,才晓得原来下面的 @Multipart 和 @PartMap 注解配合 Map<String, RequestBody> 参数是在多文件上传时用的,而这种形式默认的申请头Content-Type的值就是 multipart/form-data @FormUrlEncoded@POST("Sys/getVersion")Observable<JsonObject> getNewVersion(@FieldMap Map<String, String> versionBody);//我须要将POST数据提交的申请形式设置为表单的 @FormUrlEncoded,其对应的参数注解能够是 @FieldMap 或者 @Field,这是简略的键值对表单申请形式对应的注解组合@Headers({"Content-Type: application/json","Accept: application/json"})@POST("Sys/getVersion")Observable<JsonObject> getNewVersion(@Body RequestBody info);//咱们也能够看到响应头的Content-Type的值为 application/json; charset=utf-8,这阐明服务器的返回后果是JSON字符串,所以当咱们申请参数的格局是JSON字符串的时候,也是利用这个值,在申请接口处加上申请头



3.注解类型:网络申请参数

注解代码解释
@Header增加不固定的申请头
@Headers增加固定的申请头
@URL间接传入一个申请的 URL变量 用于URL设置
@Body自定义类型的数据
@PathURL地址的缺省值
@Field发送 Post申请 时提交申请的表单字段,与 @FormUrlEncoded 注解配合应用
@FieldMap同上,Map的key作为表单的键
@Part发送 Post申请 时提交申请的表单字段,与@Field的区别:性能雷同,但携带的参数类型更加丰盛,包含数据流,所以实用于 有文件上传 的场景,与 @Multipart 注解配合应用
@PartMap同上
@Query用于 @GET 办法的查问参数(Query = Url 中 ‘?’ 前面的 key-value)
@QueryMap同上
 @GET("/")       Call<String> cate(@Query("cate") String cate);   //如:url = http://www.println.net/?cate=android,其中,Query = cate

应用Retrofit就不得不提RxJava
通过RxJavaCallAdapterFactory为Retrofit增加RxJava反对:

Retrofit retrofit = new Retrofit.Builder()      .baseUrl("https://api.github.com")      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())       .build();

通过观察者模式

PersonalProtocol personalProtocol = retrofit.create(PersonalProtocol.class);rx.Observable<PersonalInfo> observable  = personalProtocol.getPersonalListInfo(12); observable.subscribeOn(Schedulers.io())                 .observeOn(AndroidSchedulers.mainThread())//最初在主线程中执行                .subscribe(new Subscriber<PersonalInfo>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                        //申请失败                    }                    @Override                    public void onNext(PersonalInfo personalInfo) {                        //申请胜利                    }                });                   //对应的接口更改成   public interface PersonalProtocol {    /**     * 用户信息     * @param page     * @return     */    @FormUrlEncoded    @POST("user/personal_list_info")    Observable<PersonalInfo> getPersonalListInfo(@Field("cur_page") int page);//    Call<Response<PersonalInfo>> getPersonalListInfo(@Field("cur_page") int page);}

四:Retrofit的源码解析
1.Retrofit2的build()办法,剖析构建Retrofit实例的build办法

public Retrofit build() {      if (baseUrl == null) {        throw new IllegalStateException("Base URL required.");      }      okhttp3.Call.Factory callFactory = this.callFactory;      if (callFactory == null) {        callFactory = new OkHttpClient();      }      Executor callbackExecutor = this.callbackExecutor;      if (callbackExecutor == null) {        callbackExecutor = platform.defaultCallbackExecutor();      }      // Make a defensive copy of the adapters and add the default Call adapter.      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));      // Make a defensive copy of the converters.      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,          callbackExecutor, validateEagerly);    }

Retrofit会和OkHttp一起应用,而咱们创立的时候没有传递OkHttp进去,build()这个办法外面会创立一个OkHttpClient(),当然你能够在里面传递进入
下面咱们能够看到,如果一个baseurl为空的话,会抛出异样

2.咱们看create办法创立一个接口的对象

 public <T> T create(final Class<T> service) {    Utils.validateServiceInterface(service);    if (validateEagerly) {      eagerlyValidateMethods(service);    }    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },        new InvocationHandler() {          private final Platform platform = Platform.get();          @Override public Object invoke(Object proxy, Method method, Object... args)              throws Throwable {            // If the method is a method from Object then defer to normal invocation.            if (method.getDeclaringClass() == Object.class) {              return method.invoke(this, args);            }            if (platform.isDefaultMethod(method)) {              return platform.invokeDefaultMethod(method, service, proxy, args);            }            ServiceMethod serviceMethod = loadServiceMethod(method);            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);            return serviceMethod.callAdapter.adapt(okHttpCall);          }        });  }

调用create()办法会返回一个范型T,咱们这里是PersonalProtocol对象,当PersonalProtocol调用本身办法的时候,因为它使用了动静代理,所以会调用invoke办法。invoke办法内先将method转换为ServiceMethod对象,再将serviceMethod和args对象传入OkHttpCall构造方法中,返回一个OkHttpCall,最初将OkHttpCall传入adapt办法,最初返回一个Call对象。
五:网络申请库的比照

结尾:在这条路上走上来, 明珠会交到我手中。