关于Android中 MVP框架的原理你知道多少?
在Android项目中,按照MVC的分层,Activity和Fragment应该属于View层,用于展示UI界面,以及接收用户的输入,此外还要承担一些生命周期的工作。所以开发的时候我们经常把一些业务逻辑直接写在Activity里面,这非常直观方便,代价就是Activity会越来越臃肿,而在Activity中,把View和Controller抽离开来,而这就是MVP模式的工作了。
MVP模式的核心思想
MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,Model类还是原来的Model。这就是MVP模式,现在这样的话,Activity的工作的简单了,只用来响应生命周期,其他工作都丢到Presenter中去完成。从上图可以看出,Presenter是Model和View之间的桥梁,为了让结构变得更加简单,View并不能直接对Model进行操作,这也是MVP与MVC最大的不同之处。
MVP模式的作用
- 分离了视图逻辑和业务逻辑,降低了耦合
- Activity只处理生命周期的任务,代码变得更加简洁
- 视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
- Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
- 把业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM
应用举例
在这里使用一个在ListView中更新适配器数据的例子来简单说明MVP模式是怎么使用的。
1.项目结构
在这里,颜色标注的即是我们用到的
2. model层
使用的是GsonFormat插件自动生成的bean,因此model层不需要关注bean,但由于使用了Retrofit Rxjava。
PS:使用Retrofit是因为可以很简单处理异步请求,而使用Rxjava是因为可以将被观察者跟观察者的调度任务自动切换io跟ui线程。 因此,在model层,只需要关心manager怎么组织即可。
public class DataManager {
private RetrofitService mRetrofitService;
public DataManager(){
this.mRetrofitService = RetrofitHelper.getInstance()
.getRetrofit("http://api.douban.com/v2/").getServer();
}
public ObservablegetDoubanInfo(){
return mRetrofitService.getInTheaters();
}
}
3. present层
present就是用来处理所有业务逻辑工作的代理层,假设我们在Activity/Fragment中可以把工作丢给present来处理,那会有哪些方法呢?
更新上映电影的数据
提供页面跳转时的方法 于是就有了IDoubanPresenter这个接口
public interface IDoubanPresenter {
void updateInTheaters();
void reachDetail();
}
那么它的实现则为
public class DoubanPresenter implements IDoubanPresenter {
private DataManager dataManager;
private CompositeSubscription mCompositeSubscription;
private IDoubanView mIDoubanView;
private int index;
public Douban mDouban;
public DoubanPresenter (IDoubanView view){
this.mIDoubanView = view;
dataManager = new DataManager();
mCompositeSubscription = new CompositeSubscription();
}
public void onStop() {
if (mCompositeSubscription.hasSubscriptions()){
mCompositeSubscription.unsubscribe();
}
}
@Override
public void updateInTheaters(){
mCompositeSubscription.add(dataManager.getDoubanInfo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer(){
@Override
public void onCompleted() {
if (mDouban != null){
mIDoubanView.updateInTheaters(mDouban);
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(Douban douban) {
mDouban = douban;
}
}
)
);
}
@Override
public void reachDetail(){
mCompositeSubscription.add(dataManager.getDoubanInfo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer(){
@Override
public void onCompleted() {
if (mDouban != null){
mIDoubanView.enterDetail(mDouban, index);
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(Douban douban) {
mDouban = douban;
}
}
)
);
}
}
在Present中可以看到,我们持有dataManager跟view的实例,因为业务逻辑都在这里处理,dataManager用来处理数据很好理解,view在这里不做真正的操作,只是执行一个接口方法,剩下的在接口实现里完成。
4. view层
view层其实就是我们的Activity或者Fragment。在使用List更新豆瓣接口数据,UI操作需要的方法有
- 更新上映电影的View
- 页面跳转时的方法
- 异常时怎么显示 于是就有了IDoubanView这个接口
public interface IDoubanView {
void updateInTheaters(Douban mDouban);
void enterDetail(Douban mDouban, int index);
void onError(String result);
}
然后我们在Fragment中实现这个接口
public class DoubanFragment extends Fragment implements IDoubanView {
private ListView listView;
private DoubanItemAdapter mAdapter;
private DoubanPresenter mDoubanPresenter;
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.card_fragment, container, false);
listView = view.findViewById(R.id.card_listview);
mDoubanPresenter = new DoubanPresenter(this);
mDoubanPresenter.updateInTheaters();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView adapterView, View view, int i, long l) {
mDoubanPresenter.reachDetail();
}
}
);
return view;
}
@Override
public void updateInTheaters(Douban mDouban) {
mAdapter = new DoubanItemAdapter(getActivity(), mDouban.getSubjects());
listView.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
}
@Override
public void enterDetail(Douban mDouban, int index) {
Intent mIntent = new Intent(getActivity(), WebActivity.class);
mIntent.putExtra("url", mDouban.getSubjects().get(index).getAlt());
startActivity(mIntent);
}
@Override
public void onError(String result) {
}
}
其中updateInTheaters跟enterDetail这两个接口方法由prisent调用实现。所以这个链路变成Activity/Fragment(移交任务) -> Present(数据处理) -> Activity/Fragment(渲染view)。
关于“关于Android中 MVP框架的原理你知道多少?”的内容就介绍到这,感谢各位的阅读,相信大家对关于Android中 MVP框架的原理已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注网络,小编将为大家输出更多高质量的实用文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 关于Android中 MVP框架的原理你知道多少?
本文地址: https://pptw.com/jishu/655024.html
