當下最流行的網路請求組合,retrofit2+okhttp+rxjava+mvp 這裡是封裝記錄篇 首先分模塊,比如登錄 先來說封裝後的使用 package com.fragmentapp.login.presenter; import android.util.Log; import com.fr ...
當下最流行的網路請求組合,retrofit2+okhttp+rxjava+mvp
這裡是封裝記錄篇
首先分模塊,比如登錄
先來說封裝後的使用
package com.fragmentapp.login.presenter; import android.util.Log; import com.fragmentapp.base.BasePresenter; import com.fragmentapp.http.BaseObserver; import com.fragmentapp.http.BaseResponses; import com.fragmentapp.login.bean.LoginDataBean; import com.fragmentapp.login.imple.ILoginModel; import com.fragmentapp.login.imple.ILoginView; import com.fragmentapp.login.model.LoginModel; /** * Created by liuzhen on 2017/11/3. */ public class LoginPresenter extends BasePresenter { private ILoginView view; private ILoginModel model; public LoginPresenter(ILoginView view){ this.view = view; model = new LoginModel(); } public void login(String username,String pwd){ model.login(observer,username,pwd); } BaseObserver<BaseResponses<LoginDataBean>> observer = new BaseObserver<BaseResponses<LoginDataBean>>(){ @Override public void onNextResponse(BaseResponses<LoginDataBean> loginDataBean) { Log.e("token",loginDataBean.getData().getHCACCESSTOKEN()+""); view.success(loginDataBean.getData()); } @Override public void onErrorResponse(BaseResponses<LoginDataBean> loginDataBean) { view.error(); } @Override public void onNetWorkError(String val) { view.error(); } }; }Presenter
通過p層的介面來交互,model去訪問網路請求,然後返回結果回調返回到view層去刷新
這裡自定義了一個base的obsever類,避免多次的傳遞介面
model則負責調用網路請求了
package com.fragmentapp.login.model; import com.fragmentapp.http.BaseObserver; import com.fragmentapp.http.BaseResponses; import com.fragmentapp.http.RetrofitHelper; import com.fragmentapp.login.bean.LoginDataBean; import com.fragmentapp.login.imple.ILoginModel; import java.util.HashMap; import java.util.Map; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; /** * Created by liuzhen on 2017/11/7. */ public class LoginModel implements ILoginModel { @Override public void login(final BaseObserver<BaseResponses<LoginDataBean>> observer,String username,String pwd) { Map<String, String> map = new HashMap<>(); map.put("account[username]", username); map.put("account[password]", pwd); RetrofitHelper.getInstance().getService() .login(map) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); } }View Code
view層的回調也只有兩個介面,可以根據自己的需求添加
package com.fragmentapp.login.imple; import com.fragmentapp.login.bean.LoginDataBean; /** * Created by liuzhen on 2017/11/6. */ public interface ILoginView { void success(LoginDataBean dataBean); void error(); }View Code
訪問網路後直接在activity里處理回調的結果刷新界面等
這裡的retrofit的訪問url是用的添加頭部tag來達到動態訪問替換baseurl的目的
package com.fragmentapp.http; import android.util.Log; import com.fragmentapp.BuildConfig; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; /** * Created by liuzhen on 2017/11/3. */ public class RetrofitHelper { private static final String BASE_URL_USER = "http://testapi.hanmaker.com"; private static final String BASE_URL_PAY = "https://www.222.com/"; private static final long TIME_OUT = 5000; private RetrofitHelper(){} private static class SingleHolder { private static final RetrofitHelper INSTANCE = new RetrofitHelper(); } public static final RetrofitHelper getInstance() { return SingleHolder.INSTANCE; } private static final long DEFAULT_TIMEOUT = 15L; final static Gson gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .serializeNulls()// 調用serializeNulls方法,改變gson對象的預設行為,null值將被輸出 .create(); //addInterceptor:設置應用攔截器,可用於設置公共參數,頭信息,日誌攔截等 //addNetworkInterceptor:網路攔截器,可以用於重試或重寫 //setLevel NONE(不記錄) BASIC(請求/響應行) HEADER(請求/響應行 + 頭) BODY(請求/響應行 + 頭 + 體) //cookieJar:保持在同一個會話裡面 //TimeUnit.SECONDS秒做單位 private static OkHttpClient okHttpClient = new OkHttpClient.Builder() .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .retryOnConnectionFailure(true)//錯誤重聯 .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { //獲取request Request request = chain.request(); if (BuildConfig.DEBUG) { // Log.e("request",request.toString()); } //獲取request的創建者builder Request.Builder builder = request.newBuilder(); //從request中獲取headers,通過給定的鍵url_name List<String> headerValues = request.headers("url_name"); if (headerValues != null && headerValues.size() > 0) { //如果有這個header,先將配置的header刪除,因此header僅用作app和okhttp之間使用 builder.removeHeader("url_name"); //匹配獲得新的BaseUrl String headerValue = headerValues.get(0); HttpUrl newBaseUrl = null; if ("user".equals(headerValue)) { newBaseUrl = HttpUrl.parse(BASE_URL_USER); } else if ("pay".equals(headerValue)) { newBaseUrl = HttpUrl.parse(BASE_URL_PAY); } else{ newBaseUrl = HttpUrl.parse(BASE_URL_USER); } //從request中獲取原有的HttpUrl實例oldHttpUrl HttpUrl oldHttpUrl = request.url(); //重建新的HttpUrl,修改需要修改的url部分 HttpUrl newFullUrl = oldHttpUrl .newBuilder() .scheme(newBaseUrl.scheme())//設置網路協議 .host(newBaseUrl.host())//更換主機名 .port(newBaseUrl.port())//更換埠 .build(); //重建這個request,通過builder.url(newFullUrl).build(); //然後返回一個response至此結束修改 return chain.proceed(builder.url(newFullUrl).build()); } else { return chain.proceed(request); } } }) .build(); private static Retrofit retrofit = null; private static <T> T createApi(Class<T> clazz) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL_USER) .client(okHttpClient) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); return retrofit.create(clazz); } private RetrofitService service = null; public RetrofitService getService(){ if (service == null) service = createApi(RetrofitService.class); return service; } }View Code
然後介面參數採用map的方式添加,個人感覺一個個分開來跟煩,每次都得改service類
然後observable套用了一層類型,這裡主要是後臺數據格式吭,可以去掉
package com.fragmentapp.http; /** * Created by liuzhen on 2017/11/3. */ public class BaseResponses<T> { private String info; private int status; private T data; public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public T getData() { return data; } public void setData(T data) { this.data = data; } }View Code
然後是base的observer類,在裡面根據自己的業務去回調自定義的介面,這樣就不用每次重載這麼多的方法了
package com.fragmentapp.http; import android.os.Looper; import android.util.Log; import io.reactivex.Observer; import io.reactivex.disposables.Disposable; /** * Created by liuzhen on 2017/11/3. */ public abstract class BaseObserver<T extends BaseResponses> implements Observer<T> { String TAG = getClass().getSimpleName(); @Override public void onSubscribe(Disposable d) { Log.e(TAG, "onSubscribe"); } @Override public void onNext(T t) { Log.e(TAG, "onNext"+t); if (t.getStatus() == 200) { onNextResponse(t); } else { Log.e(TAG, "ErrorStatus:" + t.getStatus() + "ErrorInfo" + t.getInfo()); onErrorResponse(t); } } @Override public void onError(Throwable e) { Log.e(TAG, "onError" + e.toString()); onNetWorkError("onError 網路超時,請重新嘗試--"+e.getMessage()); if (Looper.myLooper() == null) { Looper.prepare(); Log.e(TAG,"onError 網路超時,請重新嘗試"); Looper.loop(); } } @Override public void onComplete() { Log.e(TAG, "onComplete"); } /**返回成功*/ public abstract void onNextResponse(T t); /**介面失敗信息*/ public abstract void onErrorResponse(T t); /**網路錯誤*/ public abstract void onNetWorkError(String val); }View Code
這個沒啥好說的了
GitHub:https://github.com/1024477951/FragmentApp