在最近作的項目中,由於頻繁用到網絡請求,因此使用瞭如今比較流行的框架RxJava和Retrofit來代替以前的Okhttp的繁瑣請求。java
我這邊寫的比較簡單,本身在小項目中更使用的,若是須要深刻研究,進行一些封裝的,管理RxJava生命週期的,請移步http://p.codekk.com/detail/Android/RuffianZhong/Rx-Mvp。react
retrofit是用來作網絡請求操做,RxJava是用來切換線程、轉換數據操做的。android
首先第一步,使用三方的框架,確定是先添加依賴包。項目中用的Rxjava2.0、retrofit2.0,並且Rxjava2.0和Rxjava1.0並不兼容,因此使用起來須要注意。添加一下依賴。web
compile "com.squareup.retrofit2:retrofit:$rootProject.versions.libRetrofit"
compile "com.squareup.retrofit2:converter-gson:$rootProject.versions.libRetrofit"
compile "com.squareup.retrofit2:adapter-rxjava2:$rootProject.versions.libRetrofit"
compile "com.squareup.okhttp3:okhttp:$rootProject.versions.libOkhttp"
compile "com.squareup.okhttp3:logging-interceptor:$rootProject.versions.libOkhttp"
compile "io.reactivex.rxjava2:rxjava:$rootProject.versions.libRxJava"
compile "io.reactivex.rxjava2:rxandroid:$rootProject.versions.libRxAndroid"
第二步,建立一個Api實例 用來獲取接口的請求對象 在init()方法中經過baseUrl或獲得Retrofit對象, 請求方法等都是放在接口中,接口與retrofit關聯在getNetDemo()方法中實現。cookie
public class NetDemoApi {
private static NetDemoApi nInstance = new NetDemoApi();
private Retrofit mRequestDemo;
//baseUrl是每個網絡請求的前段,但必須是以 「/」結尾
private String mRequestDemoBaseUrl = "www.baidu.com/";
public static NetDemoApi getInstance(){
return nInstance;
}
private NetDemoApi(){
init();
}
private void init() {
//這一步就把baseurl和Retrofit關聯了起來,生成Retrofit對象
mRequestDemo = configure(mRequestDemoBaseUrl);
}
private NetDemo getNetDemo(){
return mRequestDemo.create(NetDemo.class);
}
//配置retrofit
private Retrofit configure(String baseUrl){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
WLog.i(message);
}
});
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//這隻網絡請求的攔截器 若是須要獲取到響應頭等相應信息,在此處就能夠得到 若是不須要能夠不寫
builder.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
Headers headers = response.headers();
List<String> cookies = headers.values("Set-Cookie");
Session session = Session.getInstance();
session.setCookies(Utils.getCookie(cookies));
Log.d(getClass().getSimpleName(),"設置cookie " + session.getCookies());
return response;
}
});
builder.addInterceptor(logging);
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(40, TimeUnit.SECONDS);
OkHttpClient client = builder.build();
return new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
//這是rxjava的轉換器,這個是rxjava2的默認適配器工廠,若是咱們須要轉換成bean,能夠添加gson的轉換器,直接添加就能夠,須要添加依賴包
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
}
第三步,寫實現的接口,這個接口中,纔是咱們須要請求的路徑 以下 @get 就是一個get請求的方法, @post就是一個post請求
網絡
@url 是直接傳入一個已知的URl進去,直接請求Url,並且跟baseUrl無關,不會跟baseUrl進行拼接;session
@Query 就是在URl後面進行鍵值對的拼接,以下 tip傳入1 ,就會把 tip=1 拼接到loginicon=true的後面,get和post請求都是這樣拼接。app
@Path 就是把傳入的字符串直接傳入註解中{uuid}中的位置處;框架
@body 是post請求時,傳入的requestBody對象;ide
@Header 能夠給網絡請求添加請求頭信息,添加Cookie就寫cookie,@Header("Cookie") String cookie,
以上傳入的url參數都會和baseUrl進行拼接,獲得一個完整的Url去進行網絡請求(除了@url)。
返回的就是Observable對象,咱們調用此方法後,得到observable對象,接下來用Rxjava進行數據解析,篩選。
public interface NetDemo {
@GET
Observable<ResponseBody> requestDemo(@url String url);
@GET("cgi-bin/mmwebwx-bin/login?loginicon=true")
Observable<ResponseBody> requestScanResult(@Query("tip") int tip,
@Query("uuid") String uuid,
@Query("r") String r,
@Query("_") String p);
@POST("qrcode/{uuid}")
Observable<ResponseBody> requestGenQRCode(@Path("uuid") String uuid,
@Body RequestBody body);
@POST("cgi-bin/mmwebwx-bin/webwxstatusnotify?lang=zh_CN")
public Observable<ResponseBody> webwxstatusnotify(@Query("pass_ticket") String passTicket,
@Header("Cookie") String cookie,
@Body RequestBody body);
}
第四步,在代碼中進行網絡請求,
Observable<ResponseBody> observable = WeChatNetApi.getInstance().getLoginInfo().requestLoginInfo(url); //返回Observable對象
observable.subscribeOn(Schedulers.io()) //進行網絡請求是在那個線程 io 就是在子線程
.map(new Function<ResponseBody, Bitmap>() { //能夠經過map進行轉換,把結果轉換爲一個咱們須要使用的類型(如demo,返回一個bitmap類型)
@Override
public Bitmap apply(@io.reactivex.annotations.NonNull
ResponseBody responseBody) {
return BitmapFactory.decodeStream(responseBody.byteStream());
}
})
.flatMap(new Function<String, ObservableSource<Bitmap>>() { //還能夠經過flatMap轉化爲Observable對象,轉換爲Observable對象後,還能夠繼續進行轉換操做,直到咱們須要的類型
@Override
public ObservableSource<Bitmap> apply(
@io.reactivex.annotations.NonNull String uuid) {
return genQRCode(uuid);
}
}
.filter(new Func1<Community, Boolean>() { //只有返回true,纔會繼續向下走,若是返回是false,就不會繼續向下走
@Override
public Boolean call(Community community) {
return community.houses.size()>10;
}
})
.observeOn(AndroidSchedulers.mainThread()) //網絡請求結束,切換回主線程,進行數據處理,或者顯示的操做
.subscribe(new Observer<ResponseBody>() { //轉換結束,獲得了咱們須要的數據,進行顯示,先切換到主線程
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(ResponseBody body) { //訂閱後subscribe會執行的方法
messageActivity.returnTextInfo(asJsonObject, l);
}
@Override
public void onError(Throwable e) { //若是流程中有報錯,會走到此
}
@Override
public void onComplete() { //onNext以後,若是還有後續的動做,能夠在此繼續,onnext後會調用complete;
}
});
.doOnNext(new Consumer<ResponseBody>() { //doOnNext 直接訂閱是一個偷懶的寫法,這樣寫代碼比較簡潔,並且這一步操做完以後,我也不須要繼續任何操做
@Override
public void accept(@io.reactivex.annotations.NonNull ResponseBody body) throws Exception {
handleLoginInfoResponse(url,body); } }).subscribe();