裝逼開始以前,爲你們推薦兩篇文章,用來更好的學習Retrofit和Rxjava。html
在這裏咱們要感謝互聯網裝逼行業敢於獻身,甘於奉獻的的大嬸們。java
我僅表明我的,給您們跪舔了。react
Retrofit:Retrofit官網android
Rxjava:給 Android 開發人員的 RxJava 具體解釋
git
---------------這是切割線---------------github
首先配置支持的gradle文件:json
compile 'io.reactivex:rxjava:1.1.3' compile 'io.reactivex:rxandroid:1.1.0' compile 'com.squareup.retrofit2:retrofit:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.1' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
截止至本文發表前。上述支持庫都是最新版本號。網絡
貼出Retrofit官網的GET請求演示樣例:GitHubService接口app
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
網絡請求部分代碼爲:異步
String baseUrl = "https://*******"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class); Call<List<XXXEntity>> repos = service.listRepos("octocat"); repos.enqueue(new Callback<XXXEntity>() { @Override public void onResponse(Call<XXXEntity> call, Response<XXXEntity> response) { Log.i("onResponse",response.body().toString()); } @Override public void onFailure(Call<XXXEntity> call, Throwable t) { Log.i("onResponse",t.getMessage()); } });
addConverterFactory(GsonConverterFactory.create())爲設置json解析方式爲Gson。
retrofit.create採用動態代理的方式獲取GitHubService對象,並經過Callback獲取返回的數據。
---------------當Retrofit與Rxjava相遇----------------
Retrofit.Builder需要調用
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())方法,表示用Rxjava作回調。即Rxjava所講的觀察者模式。那麼網絡請求接口就需要改爲例如如下方式:
Observable<List<Repo>> listRepos(@Path("user") String user);網絡請求部分的代碼則更改成:
String baseUrl = "https://*******"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build(); service.listRepos("octocat") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<XXXEntity>() { @Override public void onCompleted() { Log.i("onCompleted","onCompleted"); } @Override public void onError(Throwable e) { Log.i("onError",e.toString()); } @Override public void onNext(XXXEntity movieEntity) { Log.i("onCompleted",movieEntity.toString()); } });假設細緻閱讀過上述兩篇文章,不難理解這部分代碼的含義。由於篇幅緣由。這裏就不在反覆了。
固然如此這般的結合,沒法知足對代碼有深度潔癖的騷年們。接下來。在此基礎上,對代碼作整體的封裝。
項目文件夾結構例如如下:
首先封裝網絡請求類HTTPHelper.java
/** * 這一部分配置常量,可以抽取出常量類 */ private static final String BASE_PATH = "http://www.weather.com.cn/";//訪問的地址 private static final long DEFAULT_TIMEOUT = 5000;//默認超時時間(毫秒) private Retrofit mRetrofit; private INetService mNetService; private HTTPHelper(){ OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); okHttpClient.addInterceptor(new HTTPInterceptor()); okHttpClient.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); mRetrofit = new Retrofit.Builder() .client(okHttpClient.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(BASE_PATH) .build(); mNetService = mRetrofit.create(INetService.class); } /** * 單例控制器 */ private static class SingletonHolder{ private static final HTTPHelper INSTANCE = new HTTPHelper(); } /** * 獲取單例對象 * @return */ public static HTTPHelper getInstance(){ return SingletonHolder.INSTANCE; }咱們需要將網絡請求回來的字符串轉換成javaBean對象,因此引入Rxjava的map轉換機制。
代碼例如如下:
private class HttpResultFunc<T> implements Func1<IModel, T> { @Override public T call(IModel iModel) { if (iModel == null){ try { throw new Exception("result model is null"); } catch (Exception e) { e.printStackTrace(); } } return (T)iModel; } }到此。配置階段結束,如下將是Rxjava的異步訂閱請求網絡並返回操做。
爲了方便Activity、Fragment等界面處理數據。封裝Subscriber接口:
package demo.myframework.common; import rx.Subscriber; /** * @Author: lizhipeng * @Data: 16/4/12 下午4:17 * @Description: 本身定義調閱者以及結果監聽接口 */ public class ResultSubscriber<T> extends Subscriber<T> { private int mRequestType; private OnResultListener<T> mListener = null; /** * 本身定義訂閱。參數用來區分網絡接口。以用來在不一樣接口操做過程當中。處理不一樣的邏輯 * @param requestType */ public ResultSubscriber(int requestType) { this.mRequestType = requestType; mListener = new OnResultListener<T>() { @Override public void onStart(int requestType) { } @Override public void onCompleted(int requestType) { } @Override public void onError(Throwable e, int requestType) { } @Override public void onNext(T t, int requestType) { } }; } @Override public void onStart() { mListener.onStart(mRequestType); } @Override public void onCompleted() { mListener.onCompleted(mRequestType); } @Override public void onError(Throwable e) { if (e != null){ mListener.onError(e,mRequestType); } } @Override public void onNext(T t) { mListener.onNext(t,mRequestType); } /** * 設置訂閱監聽器 * @param listener */ public void setOnResultListener(OnResultListener listener){ if (listener != null){ mListener = listener; } } /** * 訂閱的監聽器 * @param <T> */ public interface OnResultListener<T> { /** * 網絡請求訂閱開始 */ void onStart(int requestType); /** * 網絡請求完畢 */ void onCompleted(int requestType); /** * 網絡請求錯誤 */ void onError(Throwable e,int requestType); /** * 處理請求結果 */ void onNext(T t,int requestType); } }已天氣訪問爲例網絡請求接口爲:
package demo.myframework.interfaces; import demo.myframework.model.WeatherModel; import retrofit2.http.GET; import retrofit2.http.Path; import rx.Observable; /** * @Author: lizhipeng * @Data: 16/4/12 下午2:57 * @Description: 網絡請求接口 */ public interface INetService { @GET("data/cityinfo/{city_id}.html") Observable<WeatherModel> getWeather(@Path("city_id") String city); }
HTTPHelper.java 中 網絡請求數據方法的實現爲:
/** * 獲取網絡數據的方法 * @param cityId */ public void getWeather(String cityId, int resultType, ResultSubscriber.OnResultListener listener){ ResultSubscriber<IModel> subscriber = new ResultSubscriber<>(resultType); subscriber.setOnResultListener(listener); mNetService.getWeather(cityId) .map(new HttpResultFunc<WeatherModel>()) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(subscriber); }MainActivity實現OnResultListener接口。點擊button調用方法爲
HTTPHelper.getInstance().getWeather("101010300",CODE,MainActivity.this);一下是activity的全部代碼:
package demo.myframework.activity; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import demo.myframework.R; import demo.myframework.common.ResultSubscriber; import demo.myframework.http.HTTPHelper; import demo.myframework.model.IModel; import demo.myframework.model.WeatherModel; public class MainActivity extends AppCompatActivity implements ResultSubscriber.OnResultListener<IModel>{ private static final String TAG = "MainActivity"; private static final int CODE = 1; private Button mButton; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initData() { mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i(TAG,"onClick"); HTTPHelper.getInstance().getWeather("101010300",CODE,MainActivity.this); } }); } private void initView() { mButton = (Button) findViewById(R.id.button); mTextView = (TextView) findViewById(R.id.textview); } private void setResultSubscriber(){ } /** * 網絡請求前調用,一般顯示Progressialog * @param requestType */ @Override public void onStart(int requestType) { Log.i(TAG,"onStart"); } /** * 網絡請求完畢調用,一般銷燬Progressialog * @param requestType */ @Override public void onCompleted(int requestType) { Log.i(TAG,"onCompleted"); } /** * 網絡請求錯誤後調用 * @param e * @param requestType */ @Override public void onError(Throwable e, int requestType) { Log.i(TAG,"onError"); } /** * onNext 方法中處理請求下來的數據 * @param iModel * @param requestType */ @Override public void onNext(IModel iModel, int requestType) { Log.i(TAG,"onNext"); if (requestType == CODE){ mTextView.setText(((WeatherModel)iModel).getWeatherinfo().toString()); } } }
HTTPInterceptor.java
package demo.myframework.http; import android.util.Log; import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * @Author: lizhipeng * @Data: 16/4/12 下午5:19 * @Description: 定義http攔截器,用於設置http協議和日誌調試 */ public class HTTPInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { //封裝headers Request request = chain.request().newBuilder() .addHeader("Content-Type", "application/json") //加入請求頭信息 .build(); // Headers headers = request.headers(); String requestUrl = request.url().toString(); //獲取請求url地址 String methodStr = request.method(); //獲取請求方式 RequestBody body = request.body(); //獲取請求body String bodyStr = (body==null?"":body.toString()); //打印Request數據 Log.i("HTTP-Interceptor","requestUrl=====>"+requestUrl); Log.i("HTTP-Interceptor","requestMethod=====>"+methodStr); Log.i("HTTP-Interceptor","requestBody=====>"+body); Response response = chain.proceed(request); return response; } }
WeatherModel.java
package demo.myframework.model; /** * @Author: lizhipeng * @Data: 16/4/12 下午3:16 * @Description: 天氣信息模板 */ public class WeatherModel implements IModel{ /** * city : 朝陽 * cityid : 101010300 * temp1 : -2℃ * temp2 : 16℃ * weather : 晴 * img1 : d0.gif * img2 : n0.gif * ptime : 18:00 */ private WeatherinfoBean weatherinfo; public WeatherinfoBean getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(WeatherinfoBean weatherinfo) { this.weatherinfo = weatherinfo; } public static class WeatherinfoBean { private String city; private String cityid; private String temp1; private String temp2; private String weather; private String img1; private String img2; private String ptime; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCityid() { return cityid; } public void setCityid(String cityid) { this.cityid = cityid; } public String getTemp1() { return temp1; } public void setTemp1(String temp1) { this.temp1 = temp1; } public String getTemp2() { return temp2; } public void setTemp2(String temp2) { this.temp2 = temp2; } public String getWeather() { return weather; } public void setWeather(String weather) { this.weather = weather; } public String getImg1() { return img1; } public void setImg1(String img1) { this.img1 = img1; } public String getImg2() { return img2; } public void setImg2(String img2) { this.img2 = img2; } public String getPtime() { return ptime; } public void setPtime(String ptime) { this.ptime = ptime; } @Override public String toString() { return "WeatherinfoBean{" + "city='" + city + '\'' + ", cityid='" + cityid + '\'' + ", temp1='" + temp1 + '\'' + ", temp2='" + temp2 + '\'' + ", weather='" + weather + '\'' + ", img1='" + img1 + '\'' + ", img2='" + img2 + '\'' + ", ptime='" + ptime + '\'' + '}'; } } }凝視已經在代碼中具體說明,就不作太多解釋了。着重說一點。ResultSubscriber.java中的mRequestType是用來在連續屢次請求網絡接口時。需要在界面中作不一樣的處理而區分的屬性。使用時,最好也爲每個接口配置爲相應的惟一值。
附上GitHub地址,https://github.com/QiYuan007/EasyFrame 假設本文對你有幫助,多多start。
假設你有更好的實現方式,請與我聯繫。