近來比較火的網絡框架,自己項目中已經使用了,
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