一、工程目录
基础的一级文件夹有app(基类)、service(mvp+网络)、ui、util、view(自定义View)。
二、构建网络请求框架
1. 导入依赖
dependencies {
// Okhttp
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'
// Retrofit (Gson数据解析器、rxjava适配器)
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
// rxjava
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
}
2. 定义网络请求接口
1) 保存所有url,方便维护:Net.java
public class Net {
//baseurl
public static final String TIAN_API_URL="http://api.tianapi.com/";
//请求新闻频道
public static final String GET_NEWS_TYPE = "/channellist/index?key=7fcd5df****6e0f";
//请求分类、筛选新闻
public static final String POST_SORT_NEWS = "/allnews/index?";
}
2) 返回体Model,根据接口文档返回的json生成 :NewsRootBean.java、NewsTypeBean.java、NewsSortBean .java
public class NewsRootBean<T> {
private int code;
private String msg;
private List<T> newslist;
//省略掉getter、setter
}
3)定义接口:RetrofitService.java
public interface RetrofitService {
//请求新闻频道
@GET(Net.GET_NEWS_TYPE)
Observable<NewsRootBean<NewsTypeBean>> getNewsTypeList();
//请求分类、筛选新闻
@GET(Net.POST_SORT_NEWS)
Observable<NewsRootBean<NewsSortBean>> requestNewsSortList(@Query("key") String key, @Query("num") int num, @Query("col") int col, @Query("page") int page);
}
4)创建日志拦截器,利于更直观的查看请求日志:LogInterceptor.java
public class LogInterceptor {
public static HttpLoggingInterceptor getLogInterceptor() {
return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.i(Content.LOG_TAG,"Log--->>>" + message);
}
//设置打印数据的级别
}).setLevel(HttpLoggingInterceptor.Level.BODY);
}
}
5)初始化并创建Retrofit,提供获取RetrofitService的方法:RetrofitHelper.java
public class RetrofitHelper {
public Context context;
private Retrofit retrofit;
//创建HTTP请求,添加日志拦截器
private OkHttpClient okHttpClient=new OkHttpClient.Builder()
.addInterceptor(LogInterceptor.getLogInterceptor())
.build();
//创建Gson转换器
private GsonConverterFactory gsonConverterFactory=GsonConverterFactory.create(new GsonBuilder().create());
/**
* 获取RetrofitHelper单例
*/
private static RetrofitHelper retrofitHelper;
public static RetrofitHelper getInstance(Context context){
if(retrofitHelper==null){
retrofitHelper=new RetrofitHelper(context);
}
return retrofitHelper;
}
public RetrofitHelper(Context context){
this.context=context;
init();
}
/**
* 创建Retrofit实例
* 设置baseurl、client、Gson转换器、异步适配器
*/
private void init() {
retrofit=new Retrofit.Builder()
.baseUrl(Net.TIAN_API_URL)
.client(okHttpClient)
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
/**
* 由Retrofit获取RetrofitService接口类
*/
public RetrofitService getService(){
return retrofit.create(RetrofitService.class);
}
}
6) 接口管理器,更方便的调用接口:DataManager.java
public class DataManager {
private RetrofitService retrofitService;
public DataManager(Context context){
//拿到RetrofitService
this.retrofitService=RetrofitHelper.getInstance(context).getService();
}
//请求新闻频道
public Observable<NewsRootBean<NewsTypeBean>> getNewsTypeList(){
return retrofitService.getNewsTypeList();
}
//请求分类、筛选新闻
public Observable<NewsRootBean<NewsSortBean>> requestNewsSortList(int num,int col,int page){
return retrofitService.requestNewsSortList("7fcd5dfdc8d09980bfb4118286886e0f",num,col,page);
}
}
7)创建观察者Observer基类,定义需要实现的方法:BaseObserver.java
public abstract class BaseObserver<T> implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onComplete() {}
@Override
public void onNext(T o) {
onSuccess(o);
}
@Override
public void onError(Throwable e) {
//异常打印日志
Log.w(Content.LOG_TAG,"Throwable--->>>"+e.getMessage());
}
//匿名内部类只需实现此方法
public abstract void onSuccess(T o);
}
8)请求网络
private DataManager manager=new DataManager(context);
public void getNewsType(){
//设置请求网络和事件处理的线程、创建观察者
manager.getNewsTypeList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<NewsRootBean<NewsTypeBean>>() {
@Override
public void onSuccess(NewsRootBean<NewsTypeBean> o) {
//请求成功的操作
if(o.getCode()==200){
newsView.onSuccess(o,1);
}else{
newsView.onError(o.getMsg());
}
}
});
}
三、构建MVP架构
MVP=Model数据(数据实体)+View视图(数据可视化)+Presenter控制器(作为M与V的桥梁通信)
1. Model数据层,就是JavaBean:NewsRootBean.java 、NewsTypeBean.java 、NewsSortBean.java
3. Presenter控制器:NewsMainPresenter.java
(1) 定义接口
public interface Presenter {
void onCreate();//初始化
void onStop();
void attachView(View view);//绑定View
}
(2) 创建控制器来请求接口、绑定View、请求到数据传给View
public class NewsMainPresenter implements Presenter {
/**
* View、Model、DataManager、Context
*/
private NewsView newsView;
private NewsRootBean model;
private DataManager manager;
private Context context;
public NewsMainPresenter(Context context){
this.context=context;
}
@Override
public void onCreate() {
manager=new DataManager(context);
}
@Override
public void onStop() {}
//绑定View
@Override
public void attachView(View view) {
newsView= (NewsView) view;
}
//请求新闻频道
public void getNewsType(){
manager.getNewsTypeList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<NewsRootBean<NewsTypeBean>>() {
@Override
public void onSuccess(NewsRootBean<NewsTypeBean> o) {
//请求数据成功,将数据传给View
if(o.getCode()==200){
newsView.onSuccess(o,1);
}else{
//请求数据失败,将提示信息传给View
newsView.onError(o.getMsg());
}
}
});
}
//请求分类、筛选新闻
public void getNewsSort(int num,int col,int page){
manager.requestNewsSortList(num,col,page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseObserver<NewsRootBean<NewsSortBean>>() {
@Override
public void onSuccess(NewsRootBean<NewsSortBean> o) {
if(o.getCode()==200){
newsView.onSuccess(o,2);
}else{
newsView.onError(o.getMsg());
}
}
});
}
}
2. View视图层:NewsView.java
(1) 定义接口
public interface View {}
用type区分不同接口拿到的数据
public interface NewsView extends View {
void onSuccess(NewsRootBean object, int type);//得到数据实体类进行逻辑操作
void onError(String result);//提示失败消息
}
(2) 在Activity/Fragment 创建View的匿名内部类,从Presenter拿到数据,数据可视化。
public class MainHomeFragment extends BaseFragment {
/**
* 获取新闻类型列表
*/
public NewsView newsView=new NewsView(){
@Override
public void onSuccess(NewsRootBean object, int type) {
switch (type){
case 1://获取类型列表
tabTitleList = object.getNewslist();
//数据可视化
for (NewsTypeBean title : tabTitleList) {
tabType.addTab(tabType.newTab().setText(title.getName()));
}
colId = tabTitleList.get(0).getColid();
break;
case 2://获取分类新闻列表
newsTitleBeanList.addAll(object.getNewslist());
newsAdapter.notifyDataSetChanged();
break;
default:break;
}
}
@Override
public void onError(String result) {
ToastUtils.showMessage(result);
}
};
}
over结束