近来比较火的网络框架,自己项目中已经使用了,
1.Retrofit简单的一句话就是通过通过代理方式和注解转换成一个serviceMethod然后调用callFactory执行的okhttp3.Callt得到返回的数据serviceMethod.callAdapter.adapt(okHttpCall)来产生method所定义的返回值。
简单使用
注解 | 请求方式 | 用途 |
---|---|---|
@Path | GET | 用于替换Url路径中的变量字符 |
@Query | GET | 用于拼接在Url路径后的查询参数,但相对于直接在Url后拼接,@Query则是添加一个变量 |
@QueryMap | GET | 效果等同于多个@Query 参数为Map类型 |
@FormUrlEncoded/@Field | POST | @FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰 |
@Body | POST | 可以指定一个对象作为HTTP请求体@Body |
@FormUrlEncoded/@Field | PUT | @FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰 |
@HTTP/@Body | DELETE | @HTTP修饰表单域,以指定一个对象作为HTTP请求体@Body,此时表单域一定要写上hasBody = true |
@Multipart/@Part或者@PartMap | POST | 文件上传使用,@Multipart修饰表单域,参数@Part修饰或者参数使用@PartMap |
上面就是常用的注解
第一步
创建retrofit 对像
private static Retrofit getRetrofit() {
if (retrofit == null) {
synchronized (Http.class) {
if (retrofit == null) {
//添加一个log拦截器,打印所有的log
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
//可以设置请求过滤的水平,body,basic,headers
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//设置 请求的缓存的大小跟位置
File cacheFile = new File(MyApplication.getInstance().getmContext().getCacheDir(), "cache");
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //50Mb 缓存的大小
client = new OkHttpClient
.Builder()
.addInterceptor(addQueryParameterInterceptor()) //参数添加
.addInterceptor(addHeaderInterceptor()) // token过滤
.addInterceptor(httpLoggingInterceptor) //日志,所有的请求响应度看到
.addInterceptor(addCacheInterceptor())//缓存信息
.cache(cache) //添加缓存
.connectTimeout(12, TimeUnit.SECONDS)
.readTimeout(12, TimeUnit.SECONDS)
.writeTimeout(12, TimeUnit.SECONDS)
.build();
// 获取retrofit的实例
retrofit = new Retrofit
.Builder()
.baseUrl(UrlHelper.BASE_URL) //自己配置
.client(client)
.addConverterFactory(ResponseConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
}
}
return retrofit;
}
在这一步的时候你可以常用信息放在里面作为头部信息,在这里用到了单例模式.
第三步
创建api 接口
加上@GET 标签,标签后面是这个接口的 尾址sign/login,完整的地址应该是 baseUrl+尾址 ,参数 使用@Query标签,如果参数多的话可以用@QueryMap标 签,接收一个Map。
常见的post请求和GET请求方式,如果要传的表单形式记得要加上 @Multipart 同时注解里面@Part List<MultipartBody.Part> partList 这种方式就是常见的图片和文字上传。
从第二步可以看出创建http请求类,并在里面初始化并配置Retrofit和OkHttp: 同时采用建造者模式添加拦截比如addQueryParameterInterceptor(),addHeaderInterceptor(),
addQueryParameterInterceptor()类中:
这里设置基本信息,当hain.proceed(request)时表示进行okhttp下一步操作
addHeaderInterceptor()
设置头的基本信息。
第四步进行数据返回,在返回时做些处理重新ResponseConverterFactory extends Converter.Factory 为什么处理呢?因为后台返回来的数据有时返回有问题,
然后 通过GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> 这样子的话我直接可以得到返回的值。
public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Type type;
public GsonResponseBodyConverter(Gson gson, Type type) {
this.type = type;
}
/**
* @param value
* @return
* @throws IOException
*/
@Override
public T convert(ResponseBody value) {
int errorCode=0;
String errorMesage="";
try {
String result = value.string();
JSONObject jsonObject = new JSONObject(result);
if (ConstantUrl.IS_DENCRYPT) {
String datas = jsonObject.optString("sign");
if(jsonObject.optInt("error_code") != ConstantUrl.error_code1){
jsonObject = new JSONObject(AESUtils.decrypt(datas));
}
}
if ((jsonObject.optInt("error_code") ==ConstantUrl.error_code3)||(jsonObject.optInt("error_code") == ConstantUrl.error_code2)) {
String data = jsonObject.optString("data");
//常规数据请求接口数据
if (!TextUtils.isEmpty(data) && !data.equals("null")) {
if(type != String.class){
return new Gson().fromJson(data,type);
}else{
return (T)data;
}
} else {
//data里面没有数据
errorCode=jsonObject.optInt("error_code");
errorMesage=jsonObject.optString("error_message");
throw new ResultException(jsonObject.optInt("error_code"), jsonObject.optString("error_message"));
}
} else {
//ErrResponse 将msg解析为异常消息文本
errorCode=jsonObject.optInt("error_code");
errorMesage=jsonObject.optString("error_message");
throw new ResultException(jsonObject.optInt("error_code"), jsonObject.optString("error_message"));
}
} catch (IOException e) {
throw new ResultException(0, UiUtils.getString(R.string.httpSubmitContextNull));
} catch (JSONException e) {
throw new ResultException(0, UiUtils.getString(R.string.JsonSyntaxException));
} catch (RuntimeException e) {
ErrResponse errResponse = new ErrResponse();
errResponse.setMsg(UiUtils.getString(R.string.systemExpire));
throw new ResultException(errorCode, errorMesage);
}
}
通过gson 方式把数据转换成自己想要的,这个时候自己定义Exception处理类,
数据返回第二步 通过Rxjava把数据带回,Exception处理分为2部分,本身Exception和服务器返回的Exception,
分开处理,
public abstract class AbsAPICallback<T> extends Subscriber<T> {
protected Context mContext;
private ProgressBarDialog dialog = null;
public AbsAPICallback(Context context,boolean isLoadProgress) {
this.mContext = context;
if(isLoadProgress && dialog == null){
dialog = new ProgressBarDialog(context);
}
if(isLoadProgress && dialog!=null){
dialog.showProgress();
}
}
@Override
public void onError(Throwable e) {
if(dialog!=null&&dialog.isShowing()){
dialog.closeProgress();
}
Log.e("e","httpException = " +e);
Throwable throwable = e;
//获取最根源的异常
while (throwable.getCause() != null) {
e = throwable;
throwable = throwable.getCause();
}
if (e instanceof HttpException) {//HTTP错误
HttpException httpException = (HttpException) e;
switch (httpException.code()) {
case IntegerUtil.ABS_UNAUTHORIZED:
break;
case IntegerUtil.ABS_FORBIDDEN:
break;
case IntegerUtil.ABS_NOT_FOUND:
ToastUtil.showShort(UiUtils.getString(R.string.noNetWork));
break;
case IntegerUtil.ABS_REQUEST_TIMEOUT:
ToastUtil.showShort(UiUtils.getString(R.string.timeout));
break;
case IntegerUtil.ABS_GATEWAY_TIMEOUT:
ToastUtil.showShort(UiUtils.getString(R.string.timeout));
break;
case IntegerUtil.ABS_INTERNAL_SERVER_ERROR:
break;
case IntegerUtil.ABS_BAD_GATEWAY:
break;
case IntegerUtil.ABS_SERVICE_UNAVAILABLE:
ToastUtil.showShort(UiUtils.getString(R.string.unavailable));
break;
default:
LogUtils.d(UiUtils.getString(R.string.InternalServerError));
break;
}
} else if (e instanceof SocketTimeoutException) {
String message = UiUtils.getString(R.string.timeout);
ToastUtil.showShort(message);
ResultException resultException = new ResultException(0,message);
onResultError(resultException);
} else if (e instanceof ResultException) {//服务器返回的错误
ResultException resultException = (ResultException) e;
switchError(resultException);
} else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) {
LogUtils.d(UiUtils.getString(R.string.JsonSyntaxException));
} else if(e instanceof ConnectException){
String message = UiUtils.getString(R.string.noNetWork);
ToastUtil.showShort(message);
ResultException resultException = new ResultException(0,message);
onResultError(resultException);
}
}
/**
* 服务器返回的错误
*/
protected abstract void onResultError(ResultException ex);
protected abstract void onDone(T t);
@Override
public void onCompleted() {
}
private ConfirmDialog comfirmDialog;
private void switchError(ResultException resultException){
switch (resultException.getErrCode()){
case IntegerUtil.ABS_TOKEN_FAIL://您的账号登录异常,请重新登录!
ToastUtil.showShort(UiUtils.getString(R.string.tokenVerifyFail));
break;
case IntegerUtil.ABS_TOKEN_EXPIRE://您的账号已过期,为确保信息安全,请重新登录!
FragmentManager mamage = ((AppCompatActivity) mContext).getSupportFragmentManager();
if(comfirmDialog==null)
comfirmDialog = ConfirmDialog.newInstance("", UiUtils.getString( R.string.tokenVerifyExpire) , "稍后再说", "立即登录");
if(comfirmDialog.isVisible())
return;
comfirmDialog.setMargin(60)
.setWidth(SystemInfoUtil.getScreenWidth()*2/3)
.setOutCancel(false)
.show(mamage);
comfirmDialog.setConfirmDialogListener(new ConfirmDialog.ConfirmDialogListener(){
@Override
public void dialogStatus(int id) {
switch (id){
case R.id.cancel:
//取消 到首页
break;
case R.id.ok:
break;
}
}
});
break;
case IntegerUtil.ABS_TOKEN_POST_NULL://请求token不能为空
break;
default:
onResultError(resultException);
break;
}
}
@Override
public void onNext(T t) {
onDone(t);
if(dialog!=null&&dialog.isShowing()){
dialog.closeProgress();
}
}
最后一步,调用实现
HttpService httpService = Http.getHttpService();
Map<String, Object> map = new HashMap<String, Object>();
map.put("courseId", courseId);
httpService.payDirectInfo(RequestBodyUtils.setRequestBody(map))
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new AbsAPICallback<PayDirectInfo>(mContext, true) {
@Override
protected void onDone(PayDirectInfo strTeacher) {
@Override
public void onResultError(ResultException ex) {
ToastUtil.showToast(ex.getMessage());
}
});
}
有问题,请随时留言或加本人QQ:874993467