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;