Retrofit網路請求,工具類的封裝
阿新 • • 發佈:2019-02-08
對於Retrofit的使用我就不介紹了,使用也不難,隨便去搜兩篇文章看看。
我主要介紹的就是如何封裝,簡便使用。
一、Retrofit工具類的封裝(核心類)
/** * Retrofit工具類 */ public class RetrofitUtils { public static final String BASE_URL = "http://XXX"; /** * 超時時間 */ public static final int TIMEOUT = 60; private static volatile RetrofitUtils mInstance; private Retrofit mRetrofit; public static RetrofitUtils getInstance() { if (mInstance == null) { synchronized (RetrofitUtils.class) { if (mInstance == null) { mInstance = new RetrofitUtils(); } } } return mInstance; } private RetrofitUtils() { initRetrofit(); } /** * 初始化Retrofit */ private void initRetrofit() { OkHttpClient.Builder builder = new OkHttpClient.Builder(); // 設定超時 builder.connectTimeout(TIMEOUT, TimeUnit.SECONDS); builder.readTimeout(TIMEOUT, TimeUnit.SECONDS); builder.writeTimeout(TIMEOUT, TimeUnit.SECONDS); OkHttpClient client = builder.build(); mRetrofit = new Retrofit.Builder() // 設定請求的域名 .baseUrl(BASE_URL) // 設定解析轉換工廠,用自己定義的 .addConverterFactory(ResponseConvert.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(client) .build(); } /** * 建立API */ public <T> T create(Class<T> clazz) { return mRetrofit.create(clazz); } }
程式碼很簡單,建立後臺請求介面,呼叫create即可。
二、Converter.Factory的封裝
自己採用Gson封裝解析。 /** * 自定義Gson解析轉換 */ public class ResponseConvert extends Converter.Factory { public static ResponseConvert create() { return new ResponseConvert(); } /** * 轉換的方法 */ @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return new BodyConverter<>(type); } private class BodyConverter<T> implements Converter<ResponseBody, T> { private Gson gson; private Type type; public BodyConverter(Type type) { this.type = type; gson = new GsonBuilder() .registerTypeHierarchyAdapter(List.class, new ListTypeAdapter()) .create(); } @Override public T convert(ResponseBody value) throws IOException { String json = value.string(); return gson.fromJson(json, type); } } /** * 空列表的轉換 */ private static class ListTypeAdapter implements JsonDeserializer<List<?>> { @Override public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json != null && json.isJsonArray()) { JsonArray array = json.getAsJsonArray(); Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0]; java.util.List list = new ArrayList<>(); for (int i = 0; i < array.size(); i++) { JsonElement element = array.get(i); Object item = context.deserialize(element, itemType); list.add(item); } return list; } else { //和介面型別不符,返回空List return Collections.EMPTY_LIST; } } } }
三、Retrofit網路請求基類的封裝
/** * 後臺統一介面API */ public interface ServerApi { // 聯絡人編輯 @POST(URLS.LOGIN) Observable<ResponseBean<LoginBean>> login(@Body RequestBody requestBody); } /** * 請求網路業務的基類,AppPresenterr 的封裝 */ public class AppPresenter { protected ServerApi mApi = RetrofitUtils.getInstance().create(ServerApi.class); private static final Gson gson = new Gson(); /** * 1. 轉換 * 統一處理一些動作 */ public static <T> void convert(Observable<ResponseBean<T>> observable, Observer<T> observer) { observable .map(new Function<ResponseBean<T>, T>() { @Override public T apply(ResponseBean<T> httpResult) throws Exception { // 列印響應的物件 LogUtils.object(httpResult); // TODO 實際開發的時候統一處理一些東西 if (httpResult == null || httpResult.head == null) { throw new RuntimeException("請求資料異常"); } else if (!"1".equals(httpResult.head.bcode)) { throw new RuntimeException(httpResult.head.bmessage); } return httpResult.data; } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); } /** * 2. 執行的方法 */ public static <T> void execute(Observable<ResponseBean<T>> observable, Observer<ResponseBean<T>> observer) { observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); } /** * 3.請求資料是Json,Json轉成RequestBody */ public static RequestBody createRequestBody(Object obj) { RequestBean bean = new RequestBean<>(obj); String json = gson.toJson(bean); // 列印請求的Json LogUtils.json(json); RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json); return body; } } 有三個通用的方法: 1.convert方法,轉換、統一處理網路請求,將公共處理部分放在這方法裡面。 2.execute方法,只執行,不做任何處理操作,適用於一些不能統一處理的介面。 3.createRequestBody方法,就是統一建立請求的RequestBody。
四、具體網路請求業務類
/**
* 登入的業務類
*/
public class LoginPresenter extends AppPresenter {
/**
* 登入的介面
*/
public void login(LoginData data, Observer<LoginBean> observer) {
Observable<ResponseBean<LoginBean>> login = mApi.login(createRequestBody(data));
// 轉換
convert(login, observer);
}
}
五、測試和使用
/**
* 呼叫登入介面
*/
public void open(View view) {
LoginData loginData = new LoginData("135****5219", "12***56");
presenter.login(loginData, new DialogObserver<LoginBean>(getAppActivity()) {
@Override
public void onNext(LoginBean data) {
// TODO 做登入的成功的操作
Toast.makeText(getAppActivity(), "" + data.userInfo.nickName, Toast.LENGTH_SHORT).show();
}
});
}
六、補充,對於Observer<T>需要再次封裝。
1.如呼叫登入要顯示Dialog
2.如Activity銷燬要取消請求。
3.結合載入資料各種狀態頁面,如:載入中、載入失敗、網路異常、資料為空等等
這些都是可以統一封裝在Observer<T>裡面。