記錄使用retrofit和rejava的初步使用
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'//原生巢狀佈局
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.jakewharton:butterknife:8.8.1'//註解模式 1
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'//註解模式 2
implementation 'com.yanzhenjie.nohttp:okhttp:1.1.9'//請求網路框架
implementation 'com.github.bumptech.glide:glide:4.6.1'//圖片載入框架
implementation 'com.cjj.materialrefeshlayout:library:1.3.0'//上下拉重新整理
implementation 'com.github.xiaoyanger0825:NiceVieoPlayer:v2.2'//視訊播放框架1
implementation 'cn.jzvd:jiaozivideoplayer:6.2.12'//視訊播放框架2
implementation 'com.zaaach:toprightmenu:1.1.2'//右上角popwindow
implementation 'com.squareup.retrofit2:retrofit:2.1.0'//使用網路框架
implementation 'com.squareup.okhttp3:okhttp:3.3.1'//使用網路請求執行器
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'//資料轉換器
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'// 銜接 Retrofit & RxJava
implementation 'io.reactivex.rxjava2:rxjava:2.0.1'//網路請求介面卡
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'//網路請求介面卡
例子一實體類:
import java.util.List;
public class GankBean {
/**
* error : false
* results : [{"_id":"5be404e49d21223dd88989d3","createdAt":"2018-11-08T09:41:56.840Z","desc":"微博,微信相簿效果,微信視訊拖放效果","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno5tb0h2g308w0g01l3","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno5xiiyrg308w0g0npi"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"web","type":"Android","url":"https://github.com/moyokoo/Diooto","used":true,"who":"miaoyj"},{"_id":"5bf2281f9d21223ddba8ca16","createdAt":"2018-11-19T03:03:59.86Z","desc":"Android RecyclerView Swipe Helper,用於處理每個方向的多個操作。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno63iuwng30aw07o4qs"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/bufferapp/MultiActionSwipeHelper","used":true,"who":"lijinshanmx"},{"_id":"5bf67e5b9d21223dd8898a01","createdAt":"2018-11-28T03:40:19.457Z","desc":"彩色二維碼。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno81ar12j31lk0rxq6s"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/jabcode/jabcode","used":true,"who":"galois"},{"_id":"5bf8bad89d21223dd8898a08","createdAt":"2018-11-28T04:22:55.510Z","desc":"狀態切換,讓View狀態的切換和Activity徹底分離開。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno82s497j30k00zkgmt","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno836mamj30k00zk0t4","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno83elg8j30k00zk74n","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8a4t79j30k00zkaau","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8afptjj30u01hc406"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"web","type":"Android","url":"https://github.com/yangchong211/YCStateLayout","used":true,"who":"瀟湘劍雨"},{"_id":"5bfdef389d212230a505d139","createdAt":"2018-11-28T03:41:35.737Z","desc":"一個輕量級版本更新彈窗。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8bhivcj308c0goaac"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"web","type":"Android","url":"https://github.com/yangchong211/YCUpdateApp","used":true,"who":"瀟湘劍雨"},{"_id":"5bfe106b9d212230a505d13a","createdAt":"2018-11-28T03:50:03.453Z","desc":"一個\"高階\"的安卓模板工程。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8boymtj307i0f0jst","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8bughtj307i0f00st","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8bz8laj307i0f0mxd","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8c3m82j307i0f0jrf","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8crc2jg30900i0hbu"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/getActivity/AndroidProject","used":true,"who":"lijinshanmx"},{"_id":"5bfe11359d2122308e7445bb","createdAt":"2018-11-28T03:53:25.547Z","desc":"Simplegraph是用於簡單圖形檢視的android庫,類似於您在硬幣交換站點上看到的。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno8db6uwj305k0b4q55"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/franticnick/simplegraph","used":true,"who":"lijinshanmx"},{"_id":"5bfe11669d212230a505d13c","createdAt":"2018-11-28T03:54:14.634Z","desc":"用於模糊檢視背景的庫。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno9fgnepg30m80gokjn"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/danielzeller/Blur-LIB-Android","used":true,"who":"lijinshanmx"},{"_id":"5bfe11fc9d2122309ed76716","createdAt":"2018-11-28T03:56:44.414Z","desc":"使用lua語言了開發android應用。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno9mmdcjg30bs0kq47e","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno9tikx7g30bs0kqmzx","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno9tpjd9g30bs0kqgm8"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/hanks-zyh/luaDevAndroid","used":true,"who":"lijinshanmx"},{"_id":"5bfe12d19d2122309624cbae","createdAt":"2018-11-28T04:00:17.782Z","desc":"適用於AndroidX的ShimmerRecyclerView。","images":["https://ww1.sinaimg.cn/large/0073sXn7gy1fxnobmepu2g30go0tnncm","https://ww1.sinaimg.cn/large/0073sXn7gy1fxnobn19fig30bo0kr7d0","https://ww1.sinaimg.cn/large/0073sXn7gy1fxnobnuw4wg30go0tnx47"],"publishedAt":"2018-11-28T00:00:00.0Z","source":"chrome","type":"Android","url":"https://github.com/mike14u/shimmer-recyclerview-x","used":true,"who":"lijinshanmx"}]
*/
private boolean error;
private List<ResultsBean> results;
public boolean isError() {
return error;
}
public void setError(boolean error) {
this.error = error;
}
public List<ResultsBean> getResults() {
return results;
}
public void setResults(List<ResultsBean> results) {
this.results = results;
}
public static class ResultsBean {
/**
* _id : 5be404e49d21223dd88989d3
* createdAt : 2018-11-08T09:41:56.840Z
* desc : 微博,微信相簿效果,微信視訊拖放效果
* images : ["https://ww1.sinaimg.cn/large/0073sXn7gy1fxno5tb0h2g308w0g01l3","https://ww1.sinaimg.cn/large/0073sXn7gy1fxno5xiiyrg308w0g0npi"]
* publishedAt : 2018-11-28T00:00:00.0Z
* source : web
* type : Android
* url : https://github.com/moyokoo/Diooto
* used : true
* who : miaoyj
*/
private String _id;
private String createdAt;
private String desc;
private String publishedAt;
private String source;
private String type;
private String url;
private boolean used;
private String who;
private List<String> images;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public boolean isUsed() {
return used;
}
public void setUsed(boolean used) {
this.used = used;
}
public String getWho() {
return who;
}
public void setWho(String who) {
this.who = who;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
}
}
例子一Trofit介面
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface GetRequest_Interface {
@GET("ajax.php?a=fy&f=auto&t=auto&w=hi%20world")
Observable<Translation> getCall();
// 註解裡傳入 網路請求 的部分URL地址
// Retrofit把網路請求的URL分成了兩部分:一部分放在Retrofit物件裡,另一部分放在網路請求接口裡
// 如果接口裡的url是一個完整的網址,那麼放在Retrofit物件裡的URL可以忽略
// 採用Observable<...>介面
// getCall()是接受網路請求資料的方法
@GET("api/data/Android/20/{page}")
Observable<GankBean> getAndroidInfo(@Path("page") int page);
}
例子二實體類
import android.util.Log;
public class Translation {
/**
* status : 1
* content : {"from":"en-EU","to":"zh-CN","out":"示例","vendor":"ciba","err_no":0}
*/
private int status;
private ContentBean content;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public ContentBean getContent() {
return content;
}
public void setContent(ContentBean content) {
this.content = content;
}
public static class ContentBean {
/**
* from : en-EU
* to : zh-CN
* out : 示例
* vendor : ciba
* err_no : 0
*/
private String from;
private String to;
private String out;
private String vendor;
private int err_no;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getOut() {
return out;
}
public void setOut(String out) {
this.out = out;
}
public String getVendor() {
return vendor;
}
public void setVendor(String vendor) {
this.vendor = vendor;
}
public int getErr_no() {
return err_no;
}
public void setErr_no(int err_no) {
this.err_no = err_no;
}
}
//定義 輸出返回資料 的方法
public void show() {
Log.d("RxJava", content.out );
}
}
例子二介面
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.GET;
public interface GnakApi {
@GET("api/data/Android/10/1")
Call<GankBean> getAndroidInfo();
@GET("api/data/Android/10/1")
Observable<GankBean> getAndroidInfo2();
}
在MainActivity中如何使用:
簡單請求
case R.id.mainBtn3:
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Call<GankBean> call = retrofit1.create(GnakApi.class).getAndroidInfo();
call.enqueue(new Callback<GankBean>() {
@Override
public void onResponse(Call<GankBean> call, Response<GankBean> response) {
GankBean.ResultsBean bean = response.body().getResults().get(1);
getDataTv.setText(
"_id:" + bean.get_id() + "\n"
+ "createdAt:" + bean.getCreatedAt() + "\n"
+ "desc:" + bean.getDesc() + "\n"
+ "images:" + bean.getImages() + "\n"
+ "publishedAt:" + bean.getPublishedAt() + "\n"
+ "source" + bean.getSource() + "\n"
+ "type:" + bean.getType() + "\n"
+ "url: " + bean.getUrl() + "\n"
+ "who:" + bean.getWho());
}
@Override
public void onFailure(Call<GankBean> call, Throwable t) {
}
});
break;
配合RxJava使用
case R.id.mainBtn4:
Retrofit retrofit2 = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支援RxJava
.build();
Observable<GankBean> observable2 = retrofit2.create(GnakApi.class).getAndroidInfo2();
// 3. 傳送網路請求(非同步)
observable2.subscribeOn(Schedulers.io()) // 在IO執行緒進行網路請求
.observeOn(AndroidSchedulers.mainThread()) // 回到主執行緒 處理請求結果
.subscribe(new Observer<GankBean>() {
// 傳送請求後呼叫該複寫方法(無論請求成功與否)
@Override
public void onSubscribe(Disposable d) {
// 初始化工作
}
// 傳送請求成功後呼叫該複寫方法
@Override
public void onNext(GankBean result) {
// 對返回結果Translation類物件 進行處理
GankBean.ResultsBean bean = result.getResults().get(1);
getDataTv.setText(
"_id:" + bean.get_id() + "\n"
+ "createdAt:" + bean.getCreatedAt() + "\n"
+ "desc:" + bean.getDesc() + "\n"
+ "images:" + bean.getImages() + "\n"
+ "publishedAt:" + bean.getPublishedAt() + "\n"
+ "source" + bean.getSource() + "\n"
+ "type:" + bean.getType() + "\n"
+ "url: " + bean.getUrl() + "\n"
+ "who:" + bean.getWho());
}
// 傳送請求成功後,先呼叫onNext()再呼叫該複寫方法
@Override
public void onComplete() {
}
// 傳送請求失敗後呼叫該複寫方法
@Override
public void onError(Throwable e) {
}
});
break;
輪詢請求
case R.id.mainBtn5:
// 步驟1:建立Retrofit物件
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fy.iciba.com/") // 設定 網路請求 Url
.addConverterFactory(GsonConverterFactory.create()) //設定使用Gson解析(記得加入依賴)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支援RxJava
.build();
// 步驟2:建立 網路請求介面 的例項
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);
// 步驟3:採用Observable<...>形式 對 網路請求 進行封裝
Observable<Translation> observable = request.getCall();
// 步驟4:傳送網路請求 & 通過repeatWhen()進行輪詢
observable.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
@Override
// 在Function函式中,必須對輸入的 Observable<Object>進行處理,此處使用flatMap操作符接收上游的資料
public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
// 將原始 Observable 停止傳送事件的標識(Complete() / Error())轉換成1個 Object 型別資料傳遞給1個新被觀察者(Observable)
// 以此決定是否重新訂閱 & 傳送原來的 Observable,即輪詢
// 此處有2種情況:
// 1. 若返回1個Complete() / Error()事件,則不重新訂閱 & 傳送原來的 Observable,即輪詢結束
// 2. 若返回其餘事件,則重新訂閱 & 傳送原來的 Observable,即繼續輪詢
return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {
// 加入判斷條件:當輪詢次數 = 30次後,就停止輪詢
if (i > 30) {
// 此處選擇傳送onError事件以結束輪詢,因為可觸發下游觀察者的onError()方法回撥
return Observable.error(new Throwable("輪詢結束"));
}
// 若輪詢次數<4次,則傳送1Next事件以繼續輪詢
// 注:此處加入了delay操作符,作用 = 延遲一段時間傳送(此處設定 = 2s),以實現輪詢間間隔設定
return Observable.just(1).delay(2000, TimeUnit.MILLISECONDS);
}
});
}
}).subscribeOn(Schedulers.io()) // 切換到IO執行緒進行網路請求
.observeOn(AndroidSchedulers.mainThread()) // 切換回到主執行緒 處理請求結果
.subscribe(new Observer<Translation>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Translation result) {
// e.接收伺服器返回的資料
result.show() ;
getDataTv.setText(result.getContent().getOut());
i++;
}
@Override
public void onError(Throwable e) {
// 獲取輪詢結束資訊
}
@Override
public void onComplete() {
}
});
break;
輪詢請求2
case R.id.mainBtn7:
// 步驟1:建立Retrofit物件
Retrofit retrofit4 = new Retrofit.Builder()
.baseUrl("http://gank.io/") // 設定 網路請求 Url
.addConverterFactory(GsonConverterFactory.create()) //設定使用Gson解析(記得加入依賴)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支援RxJava
.build();
// 步驟2:建立 網路請求介面 的例項
GetRequest_Interface request4 = retrofit4.create(GetRequest_Interface.class);
// 步驟3:採用Observable<...>形式 對 網路請求 進行封裝
Observable<GankBean> observable4 = request4.getAndroidInfo(0);
// 步驟4:傳送網路請求 & 通過repeatWhen()進行輪詢
observable4.repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() {
@Override
// 在Function函式中,必須對輸入的 Observable<Object>進行處理,此處使用flatMap操作符接收上游的資料
public ObservableSource<?> apply(@NonNull Observable<Object> objectObservable) throws Exception {
// 將原始 Observable 停止傳送事件的標識(Complete() / Error())轉換成1個 Object 型別資料傳遞給1個新被觀察者(Observable)
// 以此決定是否重新訂閱 & 傳送原來的 Observable,即輪詢
// 此處有2種情況:
// 1. 若返回1個Complete() / Error()事件,則不重新訂閱 & 傳送原來的 Observable,即輪詢結束
// 2. 若返回其餘事件,則重新訂閱 & 傳送原來的 Observable,即繼續輪詢
return objectObservable.flatMap(new Function<Object, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Object throwable) throws Exception {
// 加入判斷條件:當輪詢次數 = 10次後,就停止輪詢
if (i > 10) {
// 此處選擇傳送onError事件以結束輪詢,因為可觸發下游觀察者的onError()方法回撥
return Observable.error(new Throwable("輪詢結束"));
}
// 若輪詢次數<4次,則傳送1Next事件以繼續輪詢
// 注:此處加入了delay操作符,作用 = 延遲一段時間傳送(此處設定 = 2s),以實現輪詢間間隔設定
return Observable.just(1).delay(1000, TimeUnit.MILLISECONDS);
}
});
}
}).subscribeOn(Schedulers.io()) // 切換到IO執行緒進行網路請求
.observeOn(AndroidSchedulers.mainThread()) // 切換回到主執行緒 處理請求結果
.subscribe(new Observer<GankBean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(GankBean result) {
// e.接收伺服器返回的資料
getDataTv.setText(result.getResults().get(i).getDesc());
i++;
}
@Override
public void onError(Throwable e) {
// 獲取輪詢結束資訊
}
@Override
public void onComplete() {
}
});
break;