這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
說在前面 本人能力有限,望高手勿噴。
golang
golang語言又叫go語言,是google公司為了適應高並發,兼顧開發效率而開發的一門語言。go語言的文法非常簡單,適合做伺服器端開發。所以我準備採用golang來做web後台。因為本節重點不是講解go語言。所以會比較簡單的介紹一下。
RxJava
RxJava也使用了很久,一直想記錄一些使用過程,但是由於時間問題,一直沒有寫。RxJava是一種連結風格的編程體驗,保證你使用後一定會非常喜歡。之前一直使用的是RxJava1 不過2016年11月份官方出了RxJava2,而且版本1也不會在更新維護了,所以我這裡會使用版本2 。
Retrofit
Retrofit是一個網路請求架構,是對okhttp架構的再次封裝。提供跟良好的使用體驗。我這裡採用的是retrofit2。
伺服器端
伺服器端我使用了go語言的一個架構 gin ,這個架構是兩個外國人寫的開源架構,用來寫api非常方便。
package mainimport ( "blog/src/enity" "fmt" "github.com/gin-gonic/gin")func main() { gin.SetMode(gin.ReleaseMode) router := gin.Default() router.POST("/", func(c *gin.Context) { start := c.PostForm("start") count := c.PostForm("count") fmt.Println("start: ", start, " count:", count) c.JSON(200, gin.H{ "code": "201", "msg": "success", "data": gin.H{ "name": "aa", "age": 25, "address": "成都", "sex": 1}, }) }) router.Run(":8000")}
該伺服器端的介面非常簡單,就是擷取一個json資料。
APP端
引入依賴
//rxjava2 和rxAndroid compile 'io.reactivex.rxjava2:rxjava:2.1.1' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' //retrofit2 compile 'com.squareup.retrofit2:retrofit:2.3.0' // 自動解析json資料為實體的包 compile 'com.squareup.retrofit2:converter-gson:2.3.0' //retrofit支援轉換為Rxjava的包 compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' //okhttp compile 'com.squareup.okhttp3:okhttp:3.3.0' compile 'com.squareup.okio:okio:1.8.0' compile 'com.google.code.gson:gson:2.8.1'
rxjava中有一個 Observer類型這個就是一個觀察者,也就是一個處理資料的類。還有一個是Observable類,這個類是被觀察者類,改類就是產生資料的類。在apiservice介面類中,方法getUser()返回的就是一個被觀察者,改類型使用了泛型,也就是我們可以自動解析json資料為我們的實體物件。
建立一個 apiservice介面類
public interface ApiService { @Multipart @POST("/") Observable<BaseResponseDto<User>> getUser(@Part("start") int start, @Part("count") int count);}
我們使用了result api風格的介面,一般我們介面返回json資料格式為。
{ code: "200", msg: "success", data: { }}
所以我們可以對這個資料進行封裝。
public class BaseResponseDto<T> { private String code; private String msg; private T data; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String mag) { this.msg = mag; } public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return "BaseResponseDto{" + "code='" + code + '\'' + ", mag='" + msg + '\'' + ", data=" + data + '}'; }}
在app端請求網路資料時我們總會處理各種異常問題,比如網路異常,json解析異常等,為了少些異常處理代碼,我們需要對這一部分進行封裝。我們使用的是RxJava所以我們需要對觀察者進行封裝。
public abstract class DefaultObserver<T extends BaseResponseDto> implements Observer<T> { private static String TAG="DefaultObserver"; private Context context; private BaseViewImpl baseView; private String message=""; private Disposable disposable; public DefaultObserver(Context context){ this.context=context; } public DefaultObserver(Context context,BaseViewImpl baseView){ this.baseView=baseView; this.context=context; } public DefaultObserver(Context context,BaseViewImpl baseView,String message){ this.baseView=baseView; this.message=message; this.context=context; } @Override public void onSubscribe(@NonNull Disposable d) { Log.i(TAG,"======onSubscribe======"); disposable=d; if(null!=baseView){ baseView.addDisposable(d); baseView.showProgressDialog(message); } } @Override public void onNext(@NonNull T response) { Log.i(TAG,"======onNext======"); mainThread(); if(null!=baseView){ baseView.removeDisposable(disposable); baseView.dismissProgressDialog(); }else { disposable.dispose(); } if(response.getCode().equals("200")){ onSuccess(response); }else{ onFail(response); } } @Override public void onError(@NonNull Throwable e) { Log.i(TAG,"======onError======"+e.getMessage()); if(null !=baseView){ baseView.removeDisposable(disposable); baseView.dismissProgressDialog(); }else { disposable.dispose(); } if (e instanceof HttpException) { // HTTP錯誤 ToastUtil.showShort(context,"http錯誤"); } else if (e instanceof ConnectException || e instanceof UnknownHostException) { // 串連錯誤 ToastUtil.showShort(context,"串連錯誤"); } else if (e instanceof InterruptedIOException) { // 連線逾時 ToastUtil.showShort(context,"連線逾時"); } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) { // 解析錯誤 ToastUtil.showShort(context,"解析錯誤"); } else if(e instanceof IOException){ ToastUtil.showShort(context,"IO錯誤"); }else { ToastUtil.showShort(context,"未知錯誤"); } } @Override public void onComplete() { } /** * 請求成功 * @param response */ abstract public void onSuccess(T response); /** * 請求成功後返回的資料錯誤 * @param response */ public void onFail(T response){ ToastUtil.showShort(context,response.getMsg()); }}
這樣封裝後我們只需要子類實現 onSuccess()方法就可以了,我們只關注成功擷取資料。如果想自己根據失敗進行相關的操作也可以複寫onFail()方法。
最後我們需要把之前封裝的這幾個類弄到一個網路請求類中,方便外面統一調用。使用建立了一個Htpp類。
public class Http { private static final String TAG="Http"; private static final String BASE_URL="http://127.0.0.1:8000/"; private static final int DEFAULT_TIMEOUT=5; private static Retrofit retrofit; private ApiService apiService; private Http(){ Gson gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") .create();//使用 gson coverter,統一日期請求格式 OkHttpClient.Builder builder=new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); retrofit=new Retrofit.Builder() .baseUrl(BASE_URL) .client(builder.build()) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); apiService=retrofit.create(ApiService.class); } private static class SignleHolder{ private static final Http INSTANCE=new Http(); } public static Http getInstance(){ return SignleHolder.INSTANCE; } private class LoggingInterceptor implements Interceptor{ @Override public Response intercept(Chain chain) throws IOException { Request request=chain.request(); Log.i(TAG,String.format("\n request: %s on %s \n %s %s",request.url(),chain.connection(),request.headers(),request.body().contentType())); Response response=chain.proceed(request); Log.i(TAG,String.format("\n response: %s \n body: %s \n",response.request().url(),"")); return response; } } public void getUser(DefaultObserver<BaseResponseDto<User>> observer){ apiService.getUser(0,10) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); }}
這樣封裝後 外部就可以直接使用htpp類進行調用。
public void testDefaultRxJava(){ Http.getInstance().getUser(new DefaultObserver<BaseResponseDto<User>>(MainActivity.this,this) { @Override public void onSuccess(BaseResponseDto<User> response) { Log.i(TAG,"=====onSuccess======"+response.toString()); } @Override public void onFail(BaseResponseDto<User> response) { super.onFail(response); } }); }
這樣就輕鬆實現了RxJava2+Retrofit2 的封裝。
小結
參考連結 http://www.jianshu.com/p/9674f6df910d