前言:上篇文章MVP+Databinding模式开发APP(一) 讲述的文章因为UI框架不需要访问网络所以没有用到Model,所以未能完全的体现MVP的价值。下面来进入第二部分例子。
什么是MVC?
Model:从网络上获取的数据、数据库等数据结构
View:XML
Controller:Activity\Fragment。Activity\Fragment不仅需要设置数据、展示数据还得处理用户的事件逻辑、再与Model交互。这样在复杂逻辑的页面下Acitvity或Fragment十分的臃肿,并且耦合太高,不利用后期的维护。
什么是MVP?
MVP是MVC的升级,MVP把MVC的Model层和View层分离,达到解耦的目的,并且减轻了Activity\Fragment压力,把所有的业务逻辑交给P层处理。View层只负责界面展示。代码结构会变成异常的清晰,维护成本大大降低。
预览图
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_widget"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listview_square"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
</layout>
SwipeRefreshLayout下拉刷新是谷歌自带的,在V4包下。
//用户访问数据成功时回调的接口。
public interface OnHttpCallBack<T> {
void onSuccess(T data);
void onFail(String error);
}
public class SquareContract {
public interface ISquareModel {
//获得轮播图的数据
void getHeaderData(OnHttpCallBack<AdvertisementsBean> callBacK);
//获得主体列表的数据
void getContentData(OnHttpCallBack<SubjectPiazzaModel> callBacK);
}
public interface ISquareView {
//隐藏下拉刷新进度条
void hideProgress();
//显示服务器异常提示框
void showServerErrorMsg();
//跳转到类型列表
void toTypeTopicList();
//跳转到话题详情
void toTopicDetail();
//显示无网络错误信息
void showErrorMsg();
//刷新轮播图数据
void refreshCircleData(ArrayList<String> imageDescList, ArrayList<String> urlList);
//刷新主列表数据
void refreshContentData(List<SubjectPiazzaModel.ColumnOverview> columnOverviews);
}
public interface ISquarePresenter {
//获得轮播图的数据,并在此方法中处理轮播图的业务逻辑
void getHeaderData();
//获得主体列表的数据,并在此方法中处理主体列表的业务逻辑
void getContentData();
}
}
M 、V、P三层的接口都在这里,并且附上详细的说明。
public class SquareFragment extends BaseFragment implements SquareContract.ISquareView{
private FragmentSquareBinding squareBinding;
private SquarePresenter squarePresenter;
private List<SubjectPiazzaModel.ColumnOverview> columnOverviews;
private CirclePagerBinding pagerBinding;
private SquareAdapter squareAdapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
squareBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_square,container,false);
init();
initData();
setListener();
return squareBinding.getRoot();
}
@Override
public void init() {
squarePresenter = new SquarePresenter(this);
}
@Override
public void initData() {
//初始化listView
columnOverviews=new ArrayList<>();
squareAdapter = new SquareAdapter(columnOverviews);
squareBinding.listviewSquare.setAdapter(squareAdapter);
//初始化轮播图
pagerBinding = DataBindingUtil.inflate(LayoutInflater.from(getActivity()), R.layout.circle_pager,null,false);
squareBinding.listviewSquare.addHeaderView(pagerBinding.cycleView);
//首次进入访问网络
squarePresenter.getHeaderData();
squarePresenter.getContentData();
}
@Override
public void setListener() {
//手指触摸下滑时触发
squareBinding.swipeRefreshWidget.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//刷新数据
squarePresenter.getHeaderData();
squarePresenter.getContentData();
}
});
}
@Override
public void hideProgress() {
//关闭下拉刷新
squareBinding.swipeRefreshWidget.setRefreshing(false);
}
@Override
public void refreshCircleData(ArrayList<String> imageDescList, ArrayList<String> urlList) {
ImageCycleView.ImageCycleViewListener mAdCycleViewListener = new ImageCycleView.ImageCycleViewListener() {
@Override
public void onImageClick(int position, View imageView) {
}
@Override
public void displayImage(String imageURL, ImageView imageView) {
/** 在此方法中,显示图片,可以用自己的图片加载库,也可以用本demo中的(Imageloader) */
ImageLoaderHelper.getInstance().loadImage(imageURL, imageView);
}
};
/** 设置轮播图数据 */
pagerBinding.cycleView.setImageResources(imageDescList, urlList, mAdCycleViewListener);
pagerBinding.cycleView.startImageCycle();
}
@Override
public void refreshContentData(List<SubjectPiazzaModel.ColumnOverview> columnOverviews) {
this.columnOverviews.clear();
this.columnOverviews.addAll(columnOverviews);
squareAdapter.notifyDataSetChanged();
}
@Override
public void toTypeTopicList() {
Intent intent=new Intent(getActivity(),TopicListActivity.class);
startActivity(intent);
}
@Override
public void toTopicDetail() {
Intent intent=new Intent(getActivity(),DetailTopicActivity.class);
startActivity(intent);
}
@Override
public void showErrorMsg(){
Snackbar.make(squareBinding.getRoot(),"网络不给力,请检查网络后重试!",2500).show();
}
@Override
public void showServerErrorMsg(){
Snackbar.make(squareBinding.getRoot(),"服务器异常,请联系管理员!",2500).show();
}
public class SquarePresenter implements SquareContract.ISquarePresenter{
private final SquareContract.ISquareView iSquareView;
private final SquareModel squareModel;
public SquarePresenter(SquareContract.ISquareView squareView){
iSquareView =squareView;
//初始化对应的Model
squareModel = new SquareModel();
}
@Override
public void getHeaderData( ) {
squareModel.getHeaderData(new OnHttpCallBack<AdvertisementsBean>() {
@Override
public void onSuccess(AdvertisementsBean data) {
//如果返回的状态码为成功再解析数据
if(data.errCode.equals(Constant.SUCCESS_CODE)){
//轮播图的描述
ArrayList<String> imageDescList=new ArrayList<String>();
//轮播图的图片URL地址
ArrayList<String> urlList=new ArrayList<String>();
List<AdvertisementsBean.Advertisement> advertisements = data.result.advertisements;
urlList.clear();
//循环装载数据进入List
for (int i = 0; i < advertisements.size(); i++) {
urlList.add(advertisements.get(i).coverUrl);
imageDescList.add(advertisements.get(i).description);
}
//把数据设置给轮播图
iSquareView.refreshCircleData(imageDescList, urlList);
}
//如果返回不是成功的状态码,那说明服务器出错。
else {
iSquareView.showServerErrorMsg();
}
}
@Override
public void onFail(String error) {
//网络不好,提示相应的提示
iSquareView.showErrorMsg();
}
});
}
@Override
public void getContentData( ) {
squareModel.getContentData(new OnHttpCallBack<SubjectPiazzaModel>() {
@Override
public void onSuccess(SubjectPiazzaModel data) {
//如果返回的状态码为成功再解析数据
if(data.errCode.equals(Constant.SUCCESS_CODE)){
List<SubjectPiazzaModel.ColumnOverview> columnOverviews=data.result.columnOverviews;
//刷新列表数据
iSquareView.refreshContentData(columnOverviews);
}else{
//如果返回不是成功的状态码,那说明服务器出错。
iSquareView.showServerErrorMsg();
}
//刷新成功后关闭下拉刷新进度条
iSquareView.hideProgress();
}
@Override
public void onFail(String error) {
//刷新失败后关闭下拉刷新进度条,并且显示网络错误提示
iSquareView.hideProgress();
iSquareView.showErrorMsg();
}
});
}
}
/**
* 此model只负责数据的获取并且转换成对应的数据结构进行保存
*/
public class SquareModel implements SquareContract.ISquareModel{
@Override
public void getHeaderData(final OnHttpCallBack<AdvertisementsBean> callBacK) {
//Constant.queryAdvertisements(Constant.LOGIN_TOKEN)获得访问地址
VolleyUtil.getInstance().get(Constant.queryAdvertisements(Constant.LOGIN_TOKEN),
new VolleyUtil.JsonCallbackListener() {
@Override
public void onSucceed(String jsonString) {
//此数据结构对应的bean
AdvertisementsBean data= GsonUtil.getInstance().fromJson(jsonString,AdvertisementsBean.class);
//回调返回数据结构
callBacK.onSuccess(data);
}
@Override
public void onFail(String errorMessage) {
callBacK.onFail(errorMessage);
}
});
}
@Override
public void getContentData(final OnHttpCallBack<SubjectPiazzaBean> callBacK) {
//Constant.subjectPiazza(Constant.LOGIN_TOKEN)获得访问地址
VolleyUtil.getInstance().get(Constant.subjectPiazza(Constant.LOGIN_TOKEN),
new VolleyUtil.JsonCallbackListener() {
@Override
public void onSucceed(String jsonString) {
SubjectPiazzaBean data=GsonUtil.getInstance().fromJson(jsonString,SubjectPiazzaBean.class);
callBacK.onSuccess(data);
}
@Override
public void onFail(String errorMessage) {
callBacK.onFail(errorMessage);
}
});
}
}
附上两个javabean的数据结构
public class AdvertisementsBean extends BaseBean {
public Result result;
public class Result{
public List<Advertisement> advertisements;
}
public class Advertisement{
public String coverHeight;
public String coverType;
public String coverUrl;
public String coverWidth;
public String description;
public String id;
public String jumpUrl;
}
}
public class SubjectPiazzaBean extends BaseBean {
public Result result;
public class Result{
public List<ColumnOverview> columnOverviews;
}
public class ColumnOverview{
public ColumnBrief columnBrief;
public List<imgView> imgViews;
}
public class ColumnBrief{
public String descrption;
public String id;
public String name;
}
public class imgView{
public String imgMediaId;
public String imgUrl;
public String subjectId;
public String subjectTitle;
}
}
看到这里代码的结构是不是异常的清晰?Activity也没有那么臃肿了?