该封装解决一个api就要注入一个方法的问题,以及网络请求统一处理。之前看了很多封装都不是自己想要的,于是自己想了个比较笨的方法。
1、定义我们简洁的ApiService
public interface BaseApiService {
@GET()
Observable<ResponseBody> get(@Url String url, @QueryMap Map<String, String> maps);
@GET()
Observable<ResponseBody> get(@Url String url);
@Streaming
@GET
Observable<ResponseBody> downloadApp(@Url String fileUrl);
@FormUrlEncoded
@POST()
Observable<ResponseBody> post(@Url String url, @FieldMap Map<String, String> map);
}
2、定义ApiManager
使用泛型定义请求接口get、post、、、,好处是不管api有多少我们都可以走一个通道,不用重新写方法,处理思路是Gosn解析:
在service中定义默认返回http3的Response,在ApiManager中定义一个转换Observable方法,把Response.string返回内容使用Gson进行包装。根据传来的参数类型,使用RX操作符flatMap进行转换我们对应的s实体类型。
public class BaseApiManager {
/**
* server 请求接口
*/
private BaseApiService apiServer;
/**
* 单例类对象
*/
private static BaseApiManager instance;
private BaseApiManager(){
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS);
builder.addInterceptor(new ReceivedCookiesInterceptor(App.getInstance()))
.addInterceptor(new AddCookiesInterceptor(App.getInstance()))
.addNetworkInterceptor(new StethoInterceptor());
Retrofit.Builder retrofit = new Retrofit.Builder()
.baseUrl(MyConstant.BASE_URI)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(new Gson()));
retrofit.client(builder.build());
apiServer = retrofit.build().create(BaseApiService.class);
}
public static synchronized BaseApiManager getApi(){
if(instance==null){
instance=new BaseApiManager();
}
return instance;
}
/**
* 执行网络请求
* @param url 已经指定了base url 可以传目录
* @param queryMap 请求参数
* @param tClass 返回对象的泛型
* @param <T> 泛型
* @return 具体Observable 对象
*/
public <T> Observable<T> executeGet(String url, final Class<T> tClass, HashMap<String,String> queryMap){
Observable<T> ob=apiServer.get(url,queryMap) .flatMap(new Func1<ResponseBody, Observable<T>>() {
@Override
public Observable<T> call(ResponseBody body) {
T t=null;
try {
String rs=body.string();
Gson gson=new Gson();
t=gson.fromJson(rs,tClass);
} catch (IOException e) {
e.printStackTrace();
}
return createObserver(t);
}
});
return ob.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
/**
* 执行网络请求
* @param url 已经指定了base url 可以传目录
* @param tClass 返回对象的泛型
* @param <T> 泛型
* @return 具体Observable 对象
*/
public <T> Observable<T> executeGet(String url, final Class<T> tClass){
Observable<T> ob=apiServer.get(url) .flatMap(new Func1<ResponseBody, Observable<T>>() {
@Override
public Observable<T> call(ResponseBody body) {
T t=null;
try {
String rs=body.string();
Gson gson=new Gson();
t=gson.fromJson(rs,tClass);
} catch (IOException e) {
e.printStackTrace();
}
return createObserver(t);
}
});
return ob.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
/**
* 执行网络请求
* @param url 已经指定了base url 可以传目录
* @param queryMap 请求参数
* @param tClass 返回对象的泛型
* @param <T> 泛型
* @return 具体Observable 对象
*/
public <T> Observable<T> executePost(String url, final Class<T> tClass, HashMap<String,String> queryMap){
Observable<T> ob=apiServer.post(url,queryMap) .flatMap(new Func1<ResponseBody, Observable<T>>() {
@Override
public Observable<T> call(ResponseBody body) {
T t=null;
try {
String rs=body.string();
Gson gson=new Gson();
t=gson.fromJson(rs,tClass);
} catch (IOException e) {
e.printStackTrace();
}
return createObserver(t);
}
});
return ob.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
/**
* 创建一个泛型的Observable
* @param t 泛型
* @param <T>Observable 返回指定的泛型
* @return
*/
private <T> Observable<T> createObserver(final T t) {
return Observable.create(new Observable.OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> subscriber) {
if(t==null){
subscriber.onError(new Throwable("t 解析是空的"));
}else{
subscriber.onNext(t);
}
subscriber.onCompleted();
}
});
}
}
3 定义一个实体解析的父类
使得我们需要请求返回的对象都继承该类,以便网络请求有的地方统一处理
public class BaseResponse{
/**
* 服务器约定的成功码
*/
private int ok_code=1;
private String message;
private int result;
private int code;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public boolean isOk(){
return ok_code==result;
}
}
4 对网络请求统一处理,这个地方其他作者写的比较好,我作了下方便自己的一些修改
在订阅的时候传入Subscriber,重写方法 onStart 、onError、onComplet、onNext。定义一个接口,该接口主要包含两个方法 onSuccess,onFailure 或许还可以包含一个_onError方法作为回掉
/**
* Created by Administrator on 2017/1/9 0009.
*/
public class BaseSubscriber<T extends BaseResponse> extends Subscriber<T> {
private Context context;
private String TAG;
private Dialog dialog;
private CallBack callBack;
TextView tv;
public BaseSubscriber(@Nullable Context context, @NonNull CallBack callBack) {
this.context = context;
this.callBack=callBack;
TAG = getClass().getSimpleName();
if (context != null) {
dialog=new Dialog(context,R.style.fullScreen);
View v= LayoutInflater.from(context).inflate(R.layout.dialog_progress,null,false);
tv=(TextView) v.findViewById(R.id.loading_text);
tv.setText("请稍等");
dialog.setContentView(v);
dialog.setCancelable(false);
}
}
private Toast toast;
private void showToast(String msg,boolean notifyNetwork) {
if(context==null && !notifyNetwork){
Log.e(TAG,msg);
return;
}
if (toast== null) {
toast=Toast.makeText(App.getInstance(), msg, Toast.LENGTH_SHORT);
}else {
toast.setText(msg);
}
toast.show();
Log.i(TAG, msg);
}
@Override
public void onStart() {
super.onStart();
boolean isNetAvailable = NetUtil.isNetworkAvailable();
Log.i(TAG, " network is available " + isNetAvailable);
if (!isNetAvailable) {
showToast("亲,网络不可用,请检查网络后再尝试!",true);
onCompleted();
return;
}
if (dialog != null){
dialog.show();
}
}
@Override
public void onCompleted() {
Log.i(TAG);
if(dialog!=null){
dialog.dismiss();
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
if (dialog != null)
dialog.dismiss();
String error="";
if (e instanceof HttpException) {
HttpException exception = (HttpException) e;
try {
error = exception.response().errorBody().string();
Log.e(TAG, "出错了 " + error);
} catch (IOException e1) {
e1.printStackTrace();
error = e1.getMessage();
Log.e(TAG, "出错了 " + error);
}
}
}
@Override
public void onNext(T t){
if(t.isOk()){
callBack.success(t);
}else{
Log.i(TAG,"request="+t.toString());
callBack.failure(t.getMessage(),t.getCode(),t.getResult());
}
}
public interface CallBack<T>{
void success(T bean);
void failure(String failure,int code,int result);
}
}
5 调用
如果ApiManager中定义几个公共重载方法或者统一处理参数,就不用每次传个Map过去,懒人专属。另外如果多个ApiService的话,可以在APiManger定义的时候写为泛型,动态传入。
HashMap<String, String> map = new HashMap<>();
map.put("phone",ShareUtils.getUserPhone());
map.put("password", ShareUtils.getPassword());
map.put("loginDevice", "android");
BaseApiManager.getApi().executePost("login",UserBean.class,map)
.subscribe(new BaseSubscriber<UserBean>(null,new BaseSubscriber.CallBack<UserBean>() {
@Override
public void success(UserBean bean) {
Log.i("----","name------------"+bean.getBody().getUsername());
ShareUtils.saveUser(bean.getBody());
startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
finish();
}
@Override
public void failure(String failure, int code, int result) {
Toast.makeText(WelcomeActivity.this,failure+" from login",Toast.LENGTH_SHORT).show();
startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
finish();
}
}));