1、介绍
- Retrofit:Retrofit是Square公司开发的一款针对Android 网络请求的框架(底层默认是基于OkHttp 实现)。
- OkHttp:也是Square公司的一款开源的网络请求库。
- RxJava :"a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。RxJava使异步操作变得非常简单。
Retrofit 负责 请求的数据 和 请求的结果,使用 接口的方式 呈现,OkHttp 负责请求的过程,RxJava 负责异步,各种线程之间的切换。
2、封装使用
添加依赖库
//网络请求okhttp3
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
//日志的拦截器
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
//Retrofit2库
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
//gson解析
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
//rxjava2库
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
创建RetrofitHelper类:这个类属于网络请求工具类,用于初始化Retrofit,okhttp连接的一些设置,设置请求API的baseUrl、gson解析方式等。还有通过接口对象,调用接口类中的方法也写在这个里面了。
package com.wjy.myokhttp.net;
import android.util.Log;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by wjy.
* Date: 2019/11/22
* Time: 9:45
* Describe: Retrofit网络请求工具类,用于初始化Retrofit,设置请求API的baseUrl、gson解析方式
*/
public class RetrofitHelper {
private static RetrofitHelper instance = null;
private static OkHttpClient okHttpClient;
private ApiService apiService;
public RetrofitHelper(OkHttpClient okHttpClient){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)//服务器地址
.addConverterFactory(GsonConverterFactory.create())//用Gson把服务端返回的json数据解析成实体
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();//生成一个Retrofit实例
apiService = retrofit.create(ApiService.class);//传入网络接口类,得到接口对象实例,调用接口类中的方法。
}
public static RetrofitHelper getInstance(){
if (instance == null){
instance = new RetrofitHelper(getOkhttpClient());
}
return instance;
}
//okhttp连接的一些设置
public static OkHttpClient getOkhttpClient(){
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)//连接超时时间
.readTimeout(20,TimeUnit.SECONDS)//读超时时间
.writeTimeout(20,TimeUnit.SECONDS)//写超时时间
.retryOnConnectionFailure(true)//失败重连
.addInterceptor(loggingInterceptor)
// .addInterceptor()//设置拦截器
.build();
return okHttpClient;
}
//日志
static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
//打印retrofit日志
Log.e("RetrofitLog", "retrofitBack = " + message);
}
});
//日志等级
//=========================以下是 通过接口对象,调用接口类中的方法================================//
public Observable<JsonObject> requestData(String url){
return apiService.requestData(url);
}
public Observable<JsonObject> requestLogin_get(String username,String pwd,String regid){
return apiService.requestLogin_get(username,pwd,regid);
}
public Observable<JsonObject> requestLogin_post(String username,String pwd,String regid){
return apiService.requestLogin_post(username,pwd,regid);
}
public Observable<JsonObject> requestLogin_get_map(Map<String,String> params){
return apiService.requestLogin_get_map(params);
}
public Observable<JsonObject> requestLogin_post_map(Map<String,String> params){
return apiService.requestLogin_post_map(params);
}
public Observable<JsonObject> requestLogin_post_body(ApiService.LoginInfo loginInfo){
return apiService.requestLogin_post_body(loginInfo);
}
public Observable<JsonObject> requestLogin_get_http(String username,String pwd,String regid){
return apiService.requestLogin_get_http(username,pwd,regid);
}
public Observable<JsonObject> requestLogin_post_http(String username,String pwd,String regid){
return apiService.requestLogin_post_http(username,pwd,regid);
}
public Observable<JsonObject> uploadImage(String tp,String code){
return apiService.uploadImage(tp,code);
}
}
定义接口:管理Retrofit的各种数据请求(post、get),包含请求api、请求参数,Retrofit 注解使用等。
package com.wjy.myokhttp.net;
import com.google.gson.JsonObject;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
/**
* Created by wjy.
* Date: 2019/11/22
* Time: 11:42
* Describe: 定义接口:管理Retrofit的各种数据请求(post、get),包含请求api、请求参数
*/
public interface ApiService {
String BASE_URL = "http://xxxxxxxxxx/";//服务器地址
//Observable<JsonObject> 中的JsonObject可以换成对应的实体类
/**
* GET后面的url中可以使用自定义的变量,如 {index}、{id}进行占位 ,并使用 @Path("index") 、@Path("id") 注解为 {index} 、{id} 提供值
* 注意:形如“?page/xxx/id/aaa”才【能】使用@Path来拼接url
* 形如“?a=xxxx&b=xxxx&c=xxxx”的url是【不能】用@Path注解来拼接的,应该使用@Query或者@QueryMap注解
* @GET("?app=weather.future&weaid=1&&appkey={key}")
* @param index
* @param id
* @return
*/
@GET("page/{index}/id/{id}")
Observable<JsonObject> requestWeather(@Path("key") int index, @Path("id") int id);
//@Query和@QueryMap注解会把参数拼接到url后面,适用于GET请求
//键值对形式
@GET("?")
Observable<JsonObject> requestWeather(@Query("app") String app,@Query("appkey") int appkey);
//Map形式
@GET("?")
Observable<JsonObject> requestWeather(@QueryMap Map<String,String> params);
//List列表形式
@GET("?")
Observable<JsonObject> requestWeather(@QueryMap List<String> stringList);
//url形式
@GET
Observable<JsonObject> requestWeather(@Url String url);
//无请求参数形式
@GET("?")
Observable<JsonObject> requestWeather();
//==============================以上为GET请求方式===========================//
//==============================以下为POST请求方式===========================//
/**
* @Field或@FieldMap做表单提交,适用于POST请求;对应POST请求,需要结合@FormUrlEncoded来使用
* @Body会将请求参数放到请求体中,所以适用于POST请求
* @Body标签不能和@FormUrlEncoded或@Multipart标签同时使用,会报错
* @return
*/
@FormUrlEncoded
@POST("/")
Observable<JsonObject> requestWeathers(@Field("app") String app,@Field("appkey") int appkey);
@FormUrlEncoded
@POST("/")
Observable<JsonObject> requestWeathers(@FieldMap Map<String,String> params);
/**
* @Body实际上是将类转换成json实体作为请求体来请求网络的
* 使用这个标签的意思是我们可以定义个实体类来封装参数,作为请求参数
* @Body标签不能和@FormUrlEncoded或@Multipart标签同时使用,会报错
* @param params
* @return
*/
@POST("/")
Observable<JsonObject> requestWeathers(@Body RequestParams params);
class RequestParams{
String app;
int appkey;
}
//==============================以下为HTTP请求方式===========================//
/**
* @HTTP请求,可配置成以上几种中的任意一种,下面就分别以一种形式来举例
*/
//@HTTP配置get请求
@HTTP(method = "GET", path = "?app=weather.future&&appkey=10003", hasBody = false)
Observable<JsonObject> requestWeather1(@Query("app") String app,@Query("appkey") int appkey);
//@HTTP配置post请求
//1.配置POST请求必须结合@FormUrlEncoded使用,否者会报错
//2.hasBody必须配置为true,否则报错
@FormUrlEncoded
@HTTP(method = "POST", path = "?", hasBody = true)
Observable<JsonObject> requestWeather2(@Field("app") String app,@Field("appkey") int appkey);
//==============================@Multipart 主要是与@POST结合使用做文件的上传===========================//
@Multipart
@POST("/")
Observable<ResponseBody> uploadFile(@Part("description") RequestBody description, @Part MultipartBody.Part file);
@Multipart
@POST("/")
Observable<ResponseBody> uploadFile(@PartMap Map<String, RequestBody> params);
//==============================@Streaming 主要做大文件下载===========================//
@GET
@Streaming
Observable<ResponseBody> downloadImage(@Url String url);
//==============================以下为使用 Call 上传图片的几种写法===========================//
/**
* 上传图文
* @param description
* @param file
* @return
*/
@Multipart
@POST("web/shrink")
Call<ResponseBody> uploadFile1(@Part("description") RequestBody description, @Part MultipartBody.Part file);
/**
* 上传一张图片
* @param file
* @return
*/
@Multipart
@POST("web/shrink")
Call<ResponseBody> uploadFile2(@Part() RequestBody file);
/**
* 上传一张图片 另一种写法
* @param file
* @return
*/
@Multipart
@POST()
Call<ResponseBody> uploadFile3(@Url String url, @Part() RequestBody file);
/**
* 上传数量确定的多张图片
* @param description
* @param img1
* @param img2
* @param img3
* @return
*/
@POST("web/shrink")
Call<ResponseBody> uploadFiles4(@Part("filename") String description,
@Part("img\"; name=\"img1.png") RequestBody img1,
@Part("img\"; name=\"img2.png") RequestBody img2,
@Part("img\"; name=\"img3.png") RequestBody img3);
/**
* 上报数量不定的多张图片 版本1
* @param params
* @return
*/
@Multipart
@POST("web/shrink")
Call<ResponseBody> uploadFile5(@PartMap Map<String, RequestBody> params);
/**
* 上报数量不定的多张图片 版本2
* @param url
* @param maps
* @return
*/
@Multipart
@POST("web/shrink")
Call<ResponseBody> uploadFile6( @Url String url, @PartMap() Map<String, RequestBody> maps);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&以上为常用请求方式的参考示例&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
//下面写几个使用测试用例
//Url形式
@GET
Observable<JsonObject> requestData(@Url String url);
//键值对形式
@GET("?s=Platform.User.Login")
Observable<JsonObject> requestLogin_get(@Query("username")String username,@Query("pwd") String pwd,@Query("regid") String regid);
@POST("/?s=Platform.User.Login")
@FormUrlEncoded
Observable<JsonObject> requestLogin_post(@Field("username") String username,@Field("pwd") String pwd,@Field("regid") String regid);
//GET请求的Map形式
@GET("?s=Platform.User.Login")
Observable<JsonObject> requestLogin_get_map(@QueryMap Map<String,String> params);
//POST请求的Map形式
@FormUrlEncoded
@POST("/?s=Platform.User.Login")
Observable<JsonObject> requestLogin_post_map(@FieldMap Map<String,String> params);
//@Body实际上是将类转换成json实体作为请求体来请求网络,目前没找到可以接受json格式的请求体作为参数的网络,因此这里这是从形式说明怎么使用,这是没有问题
@POST("/?s=Platform.User.Login")
Observable<JsonObject> requestLogin_post_body(@Body LoginInfo loginInfo);
class LoginInfo{
public String username;
public String pwd;
public String regid;
}
//@HTTP配置get请求
@HTTP(method = "GET", path = "?s=Platform.User.Login", hasBody = false)
Observable<JsonObject> requestLogin_get_http(@Query("username") String username,@Query("pwd") String pwd,@Query("regid") String regid);
//@HTTP配置post请求
//1.配置POST请求必须结合@FormUrlEncoded使用,否者会报错
//2.hasBody必须配置为true,否则报错
@FormUrlEncoded
@HTTP(method = "POST", path = "/?s=Platform.User.Login", hasBody = true)
Observable<JsonObject> requestLogin_post_http(@Field("username") String username,@Field("pwd") String pwd,@Field("regid") String regid);
/**
* 上传一张图片
*/
@POST("/?s=Platform.UpImg.Img")
@FormUrlEncoded
Observable<JsonObject> uploadImage(@Field("tp") String tp,@Field("code") String code);
@Headers("Content-Type: application/json")
@POST("/")
Observable<JsonObject> requestTest(@Body HandlerModel handlerModel);
class HandlerModel{
public String Action;
public Object[] Param;
}
}
在Activity中的使用:
/**
* get的Url请求
*/
private void requestGet_Url(){
RetrofitHelper.getInstance()
.requestData("http://59.110.162.30/app_updater_version.json")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* get请求
*/
private void requestLogin_get(){
RetrofitHelper.getInstance()
.requestLogin_get("13801234567","123456","100d8559092c7ef7d5a")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* post请求
*/
private void requestLogin_post(){
RetrofitHelper.getInstance()
.requestLogin_post("13801234567","123456","100d8559092c7ef7d5a")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* get请求Map
*/
private void requestLogin_get_map(){
Map<String,String> params = new HashMap<>();
params.put("username","13801234567");
params.put("pwd","123456");
params.put("regid","100d8559092c7ef7d5a");
RetrofitHelper.getInstance()
.requestLogin_get_map(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* post请求 Map
*/
private void requestLogin_post_map(){
Map<String,String> params = new HashMap<>();
params.put("username","13801234567");
params.put("pwd","123456");
params.put("regid","100d8559092c7ef7d5a");
RetrofitHelper.getInstance()
.requestLogin_post_map(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* post请求 Body
* @Body实际上是将类转换成json实体作为请求体来请求网络,目前没找到可以接受json格式的请求体作为参数的网络,因此这里这是从形式说明怎么使用,这是没有问题
*/
private void requestLogin_post_body(){
ApiService.LoginInfo loginInfo = new ApiService.LoginInfo();
loginInfo.username = "13801234567";
loginInfo.pwd = "123456";
loginInfo.regid = "100d8559092c7ef7d5a";
RetrofitHelper.getInstance()
.requestLogin_post_body(loginInfo)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* get请求 Http
*/
private void requestLogin_get_http(){
RetrofitHelper.getInstance()
.requestLogin_get_http("13801234567","123456","100d8559092c7ef7d5a")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* post请求 Http
*/
private void requestLogin_post_http(){
RetrofitHelper.getInstance()
.requestLogin_post_http("13801234567","123456","100d8559092c7ef7d5a")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
/**
* 图片上传
*/
private void requestuploadImage(){
String stream = null;
String filePath = "/sdcard/UVCCamera/img_goods.png";//图片地址
stream = Base64StringTool.getcomImageBase64(Base64StringTool.getSmallBitmap(filePath));
if (TextUtils.isEmpty(stream)) {
Toast.makeText(MainActivity.this,"图片上传失败!",Toast.LENGTH_SHORT).show();
return;
}
RetrofitHelper.getInstance()
.uploadImage("dev",stream)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new NetSubscribe<JsonObject>(MainActivity.this) {
@Override
public void onNext(JsonObject value) {
Log.e("MainActivity","onNext value="+value.toString());
}
@Override
public void onError(Throwable e) {
Log.e("MainActivity","onError e="+e);
e.printStackTrace();
}
});
}
感觉下面两篇博文也不错,谢谢:
Android版&Kotlin版RxJava2+Retrofit2+OkHttp3的基础、封装和项目中的使用
Retrofit 注解学习 @GET @POST @Query @QueryMap @Field @FieldMap @Body ...
下面附上git源码地址:https://gitee.com/AlaYu/okhttp3_retrofit2_rxjava2#okhttp3retrofit2rxjava2