Android MVP MVVM浅谈
程序员文章站
2022-07-02 10:02:55
...
关于MVC、MVP、MVVM认识及介绍,请详细阅读并深入了解
https://juejin.im/entry/56ebb4ad5bbb50004c440972关于MVC、MVP、MVVM的理解无外乎对数据的处理方式进一步的进行优化
MVP P层实现Modle层获取数据,初始化Model,View层接口实现接口方法进行数据更新,数据加载,弹窗以及提示,而Activity仍然要实现View层接口在activity中对数据进行展示,相对于MVC而言是简化了很多,但是在Activity中仍然代码臃肿,需要处理很多数据展示等操作,下面是MVP P层以及Activity中代码。
- `public class MoviePresenter implements MovieContract.IMoviePresenter {
MovieContract.IMovieModel mIMovieModel;//M层
MovieContract.IMovieView mIMovieView;//V层
public int start = 0;//从第几个开始
public int count = 4;//请求多少个
`
List<Movies.SubjectsBean> mMovies = new ArrayList<>();//请求到的电影信息对象集合
public MoviePresenter(MovieContract.IMovieView mIMovieView) {
this.mIMovieView = mIMovieView;
mIMovieModel = new MovieModel();
}
@Override
public void getMovie() {
mIMovieView.showProgress();//通知V层显示对话框
//每次刷新加载4个
mIMovieModel.getMovie(start, count, new OnHttpCallBack<Movies>() {//有一个请求结果的回调,即我调用请求电影信息的方法了,M层要返回一个成功还是失败的信息给我
@Override
public void onSuccessful(Movies movies) {//获取电影信息成功了,返回movies对象
mIMovieView.hideProgress();//通知V层隐藏对话框
mMovies.addAll(movies.getSubjects());//追加数据
mIMovieView.showData(mMovies);//将获取到的信息显示到界面之前
mIMovieView.showBottom(start - 5);//实现换页效果
}
@Override
public void onFaild(String errorMsg) {
mIMovieView.hideProgress();//通知V层隐藏对话框
mIMovieView.showInfo(errorMsg);//通知V层显示错误信息
}
});
start = start + 4;//改变请求的起点
}
/**
* 加载更多
*/
@Override
public void loadMoreMovie() {
getMovie();
}
**Activity端代码**
public class MovieActivity extends BaseActivity implements MovieContract.IMovieView {
MoviePresenter mMoviePresenter;
private ProgressDialog mProgressDialog;
@InjectView(R.id.rv_movie_list)
RecyclerView rvMovieList;
@InjectView(R.id.store_house_ptr_frame)
PtrFrameLayout storeHousePtrFrame;
private TextView load_more;//加载更多的按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
mMoviePresenter = new MoviePresenter(this);
mMoviePresenter.getMovie();//启动软件时默认加载
}
@Override
protected void $setToolBar() {
super.$setToolBar();
setTitle("豆瓣Top250的电影");
setLeftImage(R.drawable.back);
setRightTitle("电影");
}
/**
* 初始化布局
*/
private void initView() {
setContentView(R.layout.content_movie);
ButterKnife.inject(this);
$setToolBar();
initPtr();
rvMovieList.setLayoutManager(new LinearLayoutManager(mActivity));//设置为listview的布局
rvMovieList.setItemAnimator(new DefaultItemAnimator());//设置动画
rvMovieList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));//添加分割线
}
/**
* 初始化(配置)下拉刷新组件
*/
private void initPtr() {
//下面是一些基础的配置,直接拿来用就可以 不用深究
storeHousePtrFrame.setResistance(1.7f);
storeHousePtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);
storeHousePtrFrame.setDurationToClose(200);
storeHousePtrFrame.setDurationToCloseHeader(1000);
storeHousePtrFrame.setPullToRefresh(false);
storeHousePtrFrame.setKeepHeaderWhenRefresh(true);
StoreHouseHeader header = new StoreHouseHeader(this);
float scale = getResources().getDisplayMetrics().density;
header.setPadding(0, (int) (15 * scale + 0.5f), 0, (int) (15 * scale + 0.5f));
header.initWithString("GY");//自定义头显示的字样,设置图片的话看另外的api
// header.invalidateDrawable();
header.setTextColor(Color.RED);
header.setBackgroundColor(Color.parseColor("#11000000"));
storeHousePtrFrame.setHeaderView(header);//添加头
storeHousePtrFrame.addPtrUIHandler(header);//同时也要加上这一句
storeHousePtrFrame.setPtrHandler(new PtrHandler() {
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
}
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
mMoviePresenter.loadMoreMovie();//下拉刷新的时候加载更多数据
frame.postDelayed(new Runnable() {
@Override
public void run() {
storeHousePtrFrame.refreshComplete();
}
}, 150);//为了增加用户体验 延迟0.15s再通知刷新结束
}
});
}
@Override
public void showBottom(int lastIndex) {
load_more.setText("点击加载更多");//设置最底下的加载更多显示的内容 加载中-->点击加载更多
rvMovieList.scrollToPosition(lastIndex);
}
@Override
public Context getCurContext() {
return this;
}
@Override
public void showProgress() {
mProgressDialog = ProgressDialog.show(this, "提示", "正在获取中,请稍后...");
}
@Override
public void hideProgress() {
mProgressDialog.hide();
}
/**
* 显示数据
*
* @param movies
*/
@Override
public void showData(List<Movies.SubjectsBean> movies) {
//鸿洋大神的通用适配器(真的很好用哦)
CommonAdapter<Movies.SubjectsBean> commonAdapter = new CommonAdapter<Movies.SubjectsBean>(this, R.layout.movie_item, movies) {
@Override
protected void convert(ViewHolder holder, Movies.SubjectsBean subjectsBean, int position) {
String title = (position + 1) + "、" + subjectsBean.getTitle() + "/" + subjectsBean.getOriginal_title();
holder.setText(R.id.tv_movie_title, title);//设置电影名
String doc = "";
for (Movies.SubjectsBean.DirectorsBean directorsBean : subjectsBean.getDirectors()) {
doc += directorsBean.getName() + " ";
}
holder.setText(R.id.tv_movie_doc, "导演:" + doc);
String casts = "";
for (Movies.SubjectsBean.CastsBean castsBean : subjectsBean.getCasts()) {
casts += castsBean.getName() + " ";
}
holder.setText(R.id.tv_movie_art, "主演:" + casts);
String genres = "";
for (String genre : subjectsBean.getGenres()) {
genres += genre + " ";
}
holder.setText(R.id.tv_movie_type, subjectsBean.getYear() + " / " + genres);//年份+分级
holder.setText(R.id.tv_movie_grade, subjectsBean.getRating().getAverage() + "");//评分
ImageView iv_pic = holder.getView(R.id.iv_movie_pic);
Glide.with(mActivity)
.load(subjectsBean.getImages().getSmall())
.diskCacheStrategy(DiskCacheStrategy.ALL)//加快显示速度---缓存在本地磁盘
.into(iv_pic);//图片
}
};
/**
* 配置加载更多(通用适配器里面的类哦)
*/
LoadMoreWrapper mLoadMoreWrapper = new LoadMoreWrapper(commonAdapter);//加载更多的包装器(传入通用适配器)
View view = View.inflate(mActivity, R.layout.load_more, null);
//要设置一下的布局参数,因为布局填充到包装器的时候,自己的一些属性会无效
LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(mLayoutParams);
load_more = (TextView) view.findViewById(R.id.tv_load_more);
//监听点击加载更多事件
load_more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
load_more.setText("加载中...");//点击加载更多-->加载中
mMoviePresenter.loadMoreMovie();
}
});
mLoadMoreWrapper.setLoadMoreView(view);
rvMovieList.setAdapter(mLoadMoreWrapper);//注意 这里添加的是包装器 不是适配器哦
}
@Override
public void showInfo(String info) {
ToastUtils.showToast(this, info);
}
- MVVM VM层实现数据请求监听器,初始化Modle实现类,调用获取数据的方法拿到数据,在成功失败的回调方法里面对数据进行提示,刷新,加载,对UI进行数据展示,前提是你引入DataBinding引入布局,不知道的可以先去查一下MVVM引入DataBinding如何进行实现的。下面是VM以及activity代码。
public class MovieListVm implements OnHttpCallBack<Movies>{
public int start = 0;//从第几个开始
public int count = 4;//请求多少个
MovieModleBiz movieModleBiz;
private TextView load_more;//加载更多的按钮
List<Movies.SubjectsBean> mMovies = new ArrayList<>();//请求到的电影信息对象集合
private ActivityMovieBinding binding;
private Context context;
MovieAdapter movieAdapter;
private MovieListVm movieListVm;
private ProgressDialog mProgressDialog;
public MovieListVm(Context context,ActivityMovieBinding binding){
this.binding=binding;
this.context=context;
init();
}
/**
* 初始化
*/
private void init() {
movieModleBiz = new MovieModleBiz();
firstLoadData();
}
/**
* 首次加载
*/
public void firstLoadData() {
showProgress();//通知V层显示对话框
movieModleBiz.getMovie(start, count,this);
start = start + 4;//改变请求的起点
}
@Override
public void onSuccessful(Movies movies) {
hideProgress();//通知V层隐藏对话框
mMovies.addAll(movies.getSubjects());//追加数据
movieAdapter=new MovieAdapter(context,R.layout.movie_item,mMovies);
showData(mMovies);//将获取到的信息显示到界面之前
showBottom(start - 5);//实现换页效果
}
@Override
public void onFaild(String errorMsg) {
hideProgress();//通知V层隐藏对话框
showInfo(errorMsg);//通知V层显示错误信息
}
public void showBottom(int lastIndex){
binding.rvMovieList.scrollToPosition(lastIndex);
};
public void showProgress(){
mProgressDialog = ProgressDialog.show(context, "提示", "正在获取中,请稍后...");
};//显示进度条
public void hideProgress(){
mProgressDialog.hide();
};//隐藏进度条
public void showData(List<Movies.SubjectsBean> movies){
LoadMoreWrapper mLoadMoreWrapper = new LoadMoreWrapper(movieAdapter);//加载更多的包装器(传入通用适配器)
View view = View.inflate(context, R.layout.load_more, null);
//要设置一下的布局参数,因为布局填充到包装器的时候,自己的一些属性会无效
LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(mLayoutParams);
load_more = (TextView) view.findViewById(R.id.tv_load_more);
//监听点击加载更多事件
load_more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
load_more.setText("加载中...");//点击加载更多-->加载中
firstLoadData();
}
});
mLoadMoreWrapper.setLoadMoreView(view);
binding. rvMovieList.setAdapter(mLoadMoreWrapper);//注意 这里添加的是包装器 不是适配器哦
};//显示数据到View上
public void showInfo(String info){
ToastUtils.showToast(context, info);
};//提示用户,提升友好交互
}
**Acitivity代码**
public class MvvmMoviActivity extends BaseMvVmActivity<ActivityMovieBinding>{
RecyclerView rvMovieList;
PtrFrameLayout storeHousePtrFrame;
private MovieListVm moviewListVm;
@Override
public int getLayoutId() {
return R.layout.activity_movie;
}
@Override
public void init(Bundle savedInstanceState) {
initView();
initVm();
}
private void initVm() {
moviewListVm= new MovieListVm(this, viewDataBinding);
}
private void initView() {
rvMovieList=viewDataBinding.rvMovieList;
storeHousePtrFrame=viewDataBinding.storeHousePtrFrame;
initPtr();
rvMovieList.setLayoutManager(new LinearLayoutManager(this));//设置为listview的布局
rvMovieList.setItemAnimator(new DefaultItemAnimator());//设置动画
rvMovieList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));//添加分割线
}
/**
* 初始化(配置)下拉刷新组件
*/
private void initPtr() {
//下面是一些基础的配置,直接拿来用就可以 不用深究
storeHousePtrFrame.setResistance(1.7f);
storeHousePtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);
storeHousePtrFrame.setDurationToClose(200);
storeHousePtrFrame.setDurationToCloseHeader(1000);
storeHousePtrFrame.setPullToRefresh(false);
storeHousePtrFrame.setKeepHeaderWhenRefresh(true);
StoreHouseHeader header = new StoreHouseHeader(this);
float scale = getResources().getDisplayMetrics().density;
header.setPadding(0, (int) (15 * scale + 0.5f), 0, (int) (15 * scale + 0.5f));
header.initWithString("GY");//自定义头显示的字样,设置图片的话看另外的api
// header.invalidateDrawable();
header.setTextColor(Color.RED);
header.setBackgroundColor(Color.parseColor("#11000000"));
storeHousePtrFrame.setHeaderView(header);//添加头
storeHousePtrFrame.addPtrUIHandler(header);//同时也要加上这一句
storeHousePtrFrame.setPtrHandler(new PtrHandler() {
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
}
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
//下拉刷新的时候加载更多数据
moviewListVm.firstLoadData();
frame.postDelayed(new Runnable() {
@Override
public void run() {
storeHousePtrFrame.refreshComplete();
}
}, 150);//为了增加用户体验 延迟0.15s再通知刷新结束
}
});
}
}
- 下面是在github上的源码,在了解了MVP和MVVM之后可以下载源码进行验证实现。
- github链接