retrofit基于okhttp封装的网络请求框架,网络请求的工做本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.若是你不了解OKhttp建议你仍是先了解它在来学习使用retrofit,传送门:Android 开发 框架系列 OkHttp使用详解html
Retrofit优点,就是简洁易用,解耦,扩展性强,可搭配多种Json解析框架(例如Gson),另外还支持RxJava.可是,这篇博客不讲解RxJava配合使用的部分,与RxJava的配合使用将在另一篇博客中讲解.git
另外retrofit已是封装的很是好了,已经最大程度上的匹配各类使用状况,因此不建议画蛇添足的再次封装retrofit(最多封装retrofit的单例). 再次封装不会看起来很帅也不会让你很牛逼. 只会让你看起来更蠢.把已经很拓展很解耦的实现所有破坏.github
https://github.com/square/retrofitjson
若是你不须要使用RxJava模式,那么你只须要依赖下面2个:服务器
implementation 'com.squareup.retrofit2:retrofit:2.6.2' implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
gson是用来解析的Json数据使用的(我的偏心Gson),retrofit也支持其余解析工具好比fastJson网络
老规矩按思惟顺序讲解demoapp
Retrofit配置好后,能够全局使用这一个Retrofit用来请求网络(因此你能够实现单例以全局使用),固然下面的代码只是demo:框架
private Retrofit mRetrofit; private void initHttpBase(){ mRetrofit = new Retrofit.Builder() .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的网络地址 baseUrl不能为空,且强制要求必需以 / 斜杠结尾 .addConverterFactory(GsonConverterFactory.create())//使用Gson解析 .callbackExecutor(Executors.newSingleThreadExecutor())//使用单独的线程处理 (这很重要,通常网络请求若是不设置可能不会报错,可是若是是下载文件就会报错) .build(); }
注意! base的网络地址 baseUrl不能为空,且强制要求必需以 / 斜杠结尾异步
public class LoginBean { private int code; private String message; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
public interface HttpList { @FormUrlEncoded //注解表示from表单 还有@Multipart 表单可供使用 固然你也能够不添加 @POST("test/login_test") //网络请求路径 Call<LoginBean> login(@Field("number") String number, @Field("password") String password); //@Field("number") 为post值的的key }
注意,这是一个接口类. LoginBean则是数据返回后的Bean类(Retrofit会自动使用导入的Gson解析)ide
注意! @POST("test/login_test") 这路径最前面不能加斜杠 / ,不然它会自动裁剪路径,这样会致使你的路径错误
private void postHttp(){ HttpList httpList = mRetrofit.create(HttpList.class); Call<LoginBean> call = httpList.login("181234123", "123456"); call.enqueue(new Callback<LoginBean>() { @Override public void onResponse(Call<LoginBean> call, Response<LoginBean> response) { LoginBean bean = response.body(); Log.e(TAG, "onResponse: code="+bean.getCode()); Log.e(TAG, "onResponse: message="+bean.getMessage()); } @Override public void onFailure(Call<LoginBean> call, Throwable t) { Log.e(TAG, "onFailure: 网络请求失败="+t.getMessage()); } }); }
这样,咱们就完成了一个网络请求.是否是特别简单
private void postHttp2() { HttpList httpList = mRetrofit.create(HttpList.class); final Call<LoginBean> call = httpList.login("181234123", "123456"); new Thread(new Runnable() { //Android主线程不能操做网络请求,因此new一个线程来操做 @Override public void run() { try { Response<LoginBean> response = call.execute();//同步请求网络 LoginBean bean = response.body(); Log.e(TAG, "onResponse: code=" + bean.getCode()); Log.e(TAG, "onResponse: message=" + bean.getMessage()); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
public void cancelHttp(){ HttpList httpList = mRetrofit.create(HttpList.class); //这里贴这部分代码是告诉call是哪里来的,关键点就是这个call,固然你也能够从回调里获取 mCall = httpList.login("181234123", "123456"); mCall.cancel(); //取消请求 }
以固定数据的形式添加头信息
public interface HttpList { @Headers({"content1:one","content2:two"}) @POST("test/logout_test") Call<LoginBean> logout1(); }
以非固定数据的形式添加头信息
public interface HttpList { @POST("test/logout_test") Call<LoginBean> logout2(@Header("content") String content); }
Body通常有4个种类
框架直接提供的2个Body
public interface HttpList { @FormUrlEncoded //application/x-www-form-urlencoded 表单body @POST("test/login_test") Call<LoginBean> login2(@Field("number") String number, @Field("password") String password); @Multipart //multipart/form-data 此body支持文件上传与下载 @POST("test/login_test") Call<LoginBean> login3(@Field("number") String number, @Field("password") String password); }
其余2个就须要自定义建立了,下面举例Json Body的建立:
/** * * @param string 直接导入须要发送给服务器的JSON的String值 * @return */ public static RequestBody getRequestBody(String string) { return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), string); }
在接口类参数须要设置为 @Body RequestBody requestBody
@POST("app/system/demo")
Observable<UpdateInfo> demo(@Body RequestBody requestBody);
上面说了retrofit是基于Okhttp开发的网络请求框架,因此它有一部分的功能依然须要使用Okhttp的方式来配置好比请求超时时间/设置拦截器等等,下面就展现一下如何添加
private void initHttpBase2() { OkHttpClient okHttpClient = new OkHttpClient.Builder() .retryOnConnectionFailure(false) //在链接失败时重试 .callTimeout(30, TimeUnit.SECONDS) //呼叫超时,设置此参数为总体流程请求的超时时间 .connectTimeout(20,TimeUnit.SECONDS)//链接超时 .readTimeout(20,TimeUnit.SECONDS)//读取超时 .writeTimeout(20,TimeUnit.SECONDS)//写入超时 // .callTimeout()//呼叫超时,设置此参数为总体流程请求的超时时间 // .addInterceptor() //设置拦截器 // .authenticator() //设置认证器 // .proxy()//设置代理 .build(); mRetrofit = new Retrofit.Builder() .client(okHttpClient) .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的网络地址 .addConverterFactory(GsonConverterFactory.create())//使用Gson解析 .callbackExecutor(Executors.newSingleThreadExecutor()) .build(); }
@POST("/article/query/{page}/json") @FormUrlEncoded Observable<DataResponse<Article>> getSearchArticles(@Path("page") int page, @Field("k") String k);
end