相信熟悉android开发的童鞋对MVP框架应该都不陌生吧,网上很多关于android中实现MVP的文章,大家可以直接搜索学习。这些文章中,MVP的实现思路基本都是把Activity、Fragment作为Presenter,这种方式不同于现在主流的MVP方式,不过却好的解决了Activity生命周期带来的问题,且让MVP的实现更加轻松了。
小编觉得很多关于android MVP框架的实现的文章都写的非常不错,且今天在网上看到一位童鞋利用上面所说的思路实现自己的MVP框架— MVPro,更是让人眼前一亮。下面小编和大家分享分享这位牛叉叉的童鞋是怎么实现他的MVPro的,一起来围观吧。
MVPro的原理
和以往大家实现MVP的思想类似,将Activity和Fragment作为Presenter,为了形象直观,我们通过下面这张图,来展示MVPro的原理:
MVPro的实现很简单,思想和上面两篇文章介绍的一样,都是将Activity和Fragment作为Presenter,首先一张图来解释一下MVPro的原理,
(图片没传上来,这部分只能靠大家想想了。。。。)
Presenter即我们的Activity或者Fragment, View呢?说白了就是我们从Activity和Fragment中提取出来的和View操作相关的代码,思路很简单也很清晰,下面我们就以一个简单的demo详细学习一下MVPro的使用吧。
MVPro的使用
因为MVPro是将Activity视为Presenter,所以我们代码的主线应该是Presenter了,首先上一个Presenter的代码,
public class MainActivity extends ActivityPresenterImpl<DataListView>
implements AdapterView.OnItemClickListener, View.OnClickListener {
@Override
public void create(Bundle savedInstance) {
}
@Override
public void created(Bundle savedInstance) {
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mView.toast(position);
}
@Override
public void onClick(View v) {
if(v.getId() == R.id.newdata) newData();
else getData();
}
private void newData() {
new MainBiz().data(new MainBiz.Callback<ArrayList<String>>() {
@Override
public void callback(ArrayList<String> data) {
mView.setData(data);
}
});
}
private void getData() {
new MainBiz().data(new MainBiz.Callback<ArrayList<String>>() {
@Override
public void callback(ArrayList<String> data) {
mView.addData(data);
}
});
}
}
MainActivity继承自ActivityPresenterImpl类,而且在代码中并没有任何和Activity生命周期相关的代码,两个方法create和created是我们唯一关心的重点,但是也是非必须重写的,这两个方法都是Presenter提供的方法,他们两个的区别就是create在setContentView之前调用,而created是在setContentView之后调用。
剩下的几个方法我们可以猜测到都是从View层发起的,那么接下来我们就来看看View层该如何去写。从MainActivity实现的泛型中我们可以看出,这里我们对应的View层代码在DataListView中。
/**
* Created by www.maiziedu.com on 2015/11/15.
*/
public class DataListView extends ViewImpl {
private Button mButton1, mButton2;
private ListView mListView;
private ArrayAdapter<String> mAdapter;
@Override
public void created() {
mButton1 = findViewById(R.id.newdata);
mButton2 = findViewById(R.id.adddata);
mListView = findViewById(R.id.list);
}
@Override
public void bindEvent() {
EventHelper.click(mPresenter, mButton1, mButton2);
EventHelper.itemClick(mPresenter, mListView);
}
@Override
public int getLayoutId() {
return R.layout.list_layout;
}
public void setData(ArrayList<String> datas) {
mAdapter = new ArrayAdapter<String>(mRootView.getContext(),
android.R.layout.simple_list_item_1, datas);
mListView.setAdapter(mAdapter);
}
public void addData(ArrayList<String> datas) {
mAdapter.addAll(datas);
}
public void toast(int position) {
Toast.makeText(mRootView.getContext(),
mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
}
}
在View层中,我们并不关心布局文件是怎么设置到Activity上的,我们仅仅在getLayoutId中返回我们要使用的布局文件,和created中去获取我们需要的控件即可,不过我们还重写一个bindEvent方法,在这个方法中我们为控件绑定了事件,这里需要注意一点就是MVPro希望各种事件都在Presenter上implements,因为EventHelper 提供了基于Presenter的事件监听。
ok, MVPro的使用就这么简单,不过相信很多人还是摸不着头脑,所以下面我们将会深入到源码中,来了解一下MVPro的实现流程。
MVPro源码
首先我们还是要从Presenter入手,Presenter的源头是一个接口,这里面定义了Presenter的必须需要的几个方法,
/**
* Presenter的根接口<br />
* Created by www.maiziedu.com on 2015/11/15.
*/
public interface IPresenter<T> {
/**
* 获取当前presenter泛型的类型
* @return
*/
Class<T> getViewClass();
/**
* View初始化之前可以在此方法做一些操作
*/
void create(Bundle savedInstance);
/**
* View初始化完毕后调用
*/
void created(Bundle savedInstance);
}
只有三个方法,其中getViewClass是获取我们对应的View层那个类的class, 例如上面的demo中对应的就是DataListView,create和created是两个扩展方法分别在onCreate的setContentView之前和之后调用。接下来,我们就来看看我们上面MainActivity继承的那个ActivityPresenterImpl的代码,
/**
* 将Activity作为Presenter的基类 <br />
* Created by www.maiziedu.com on 2015/11/15.
*/
public class ActivityPresenterImpl<T extends IView> extends Activity implements IPresenter<T> {
protected T mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
create(savedInstanceState);
try {
mView = getViewClass().newInstance();
mView.bindPresenter(this);
setContentView(mView.create(getLayoutInflater(), null));
mView.bindEvent();
created(savedInstanceState);
} catch(Exception e) {
throw new RuntimeException(e.getMessage());
}
}
@Override
public Class<T> getViewClass() {
return GenericHelper.getViewClass(getClass());
}
@Override
public void create(Bundle savedInstance) {
}
@Override
public void created(Bundle savedInstance) {
}
}
估计很多人在没看到ActivityPresenterImpl源码之前都会认为它应该很复杂,不过在看后大概都会忍不住吐槽一句:尼玛,这么少!对代码确实少,而且基本都集中在了onCreate中,不过,在看onCreate之前,我们首先来看看getViewClass方法,这个方法实现自IPresenter,而且仅仅有一行代码,它的作用就是获取当前Presenter泛型指定那个View层类,对应上面的demo中就是DataListView了。
接下来回到onCreate中,在onCreate中,我们首先调用了create方法,以便于我们执行一些在setContentView之前的代码,例如设置无标题啥的。
然后通过getViewClass获取到了View层的类,并且利用反射得到他的对象mView,接下的几步都和这个mView相关。
调用mView.bindPresenter方法,将当前Presenter关联到当前View层上。
调用mView.create方法生成我们布局文件对应的View对象,并且通过setContentView设置布局文件。
调用mView.bindEvent方法,在这个方法中我们可以对一些控件设置事件监听。
最后我们调用了created方法,以便在开发中书写初始化控件完毕后的代码。
Presenter的代码很简单,主要是一些流程性的东西,接下来我们来看看View层的代码是怎么实现的。还是从接口——IView开始,
/**
* View层的根接口 <br />
* Created by www.maiziedu.com on 2015/11/15.
*/
public interface IView {
/**
* 根据 {@link getLayoutId}方法生成生成setContentView需要的根布局
* @param inflater
* @param container
* @return
*/
View create(LayoutInflater inflater, ViewGroup container);
/**
* 当Activity的onCreate完毕后调用
*/
void created();
/**
* 返回当前视图需要的layout的id
* @return
*/
int getLayoutId();
/**
* 根据id获取view
* @param id
* @param <V>
* @return
*/
<V extends View> V findViewById(int id);
/**
* 绑定Presenter
* @param presenter
*/
void bindPresenter(IPresenter presenter);
/**
* {@link created}后调用,可以调用{@link org.loader.helper.EventHelper.click}
* 等方法为控件设置点击事件,一般推荐使用{@link org.loader.helper.EventHelper.click(IPresenter presenter, View ...views)}
* 方法并且让你的Presenter实现相应接口。
*/
void bindEvent();
}
IView接口中定义的方法就相对多了一些,我们一个个的来说一下这些方法存在的理由。
create方法根据提供的layout的id来生成布局对象,上面Presenter的setContentView的参数就是他的返回值。
created会在inflater布局完成后调用,以便我们一些操作。
getLayoutId需要我们去实现,返回需要的布局文件的id。
findViewById提供了一个泛型的查找控件方法,有了它我们再也不用类型转换了。
bindPresenter绑定对应的Presenter。
bindEvent我们需要实现这个方法来为控件设置监听。
在介绍完这些方法后,我们就来看看我们View层的基类都是做了什么工作。
/**
* View层的基类
* Created by www.maiziedu.com on 2015/11/15.
*/
public abstract class ViewImpl implements IView {
/**
* create方法生成的view
*/
protected View mRootView;
/**
* 绑定的presenter
*/
protected IPresenter mPresenter;
@Override
public View create(LayoutInflater inflater, ViewGroup container) {
mRootView = inflater.inflate(getLayoutId(), container, false);
created();
return mRootView;
}
@Override
public <V extends View> V findViewById(int id) {
return (V) mRootView.findViewById(id);
}
@Override
public void created() {
}
@Override
public void bindPresenter(IPresenter presenter) {
mPresenter = presenter;
}
@Override
public void bindEvent() {
}
}
在create方法中,我们使用LayoutInflater生成了View对象,并且返回给Presenter用来setContentView,在返回之前我们还调用了created方法,在项目中我们可以在这个方法中查找我们需要的控件。
created和bindEvent方法在这里都是空实现,这样做的目的就是在我们自己的代码中不需要任何时候都要实现这两个方法。
MVPro的代码大体就这些,整个流程我们也分析完了,那Model层呢?还没有看到关于Model层的代码呢!在MVPro中并不关心你业务层是怎么实现,你完全可以使用你现在正在使用的业务层代码的架构,而不会对MVP产生任何影响。
最后,我们还是要来看看EventHelper是怎么设置事件监听的。
public class EventHelper {
public static void click(IPresenter li, View ...views) {
if(!(li instanceof View.OnClickListener)) return;
click((View.OnClickListener) li, views);
}
public static void click(View.OnClickListener li, View ...views) {
if(views == null || views.length == 0) return;
for(View v : views) v.setOnClickListener(li);
}
...
}
这里拿click事件为例,可以看到我们的参数是一个IPresenter类型,而且是判断了你传递的这个Presenter是不是实现了View.OnClickListener接口,如果实现了,就进行强制类型转换使用,从这里我们也可以看到,为了尽量减少我们的Presenter和View层的代码耦合,MVPro并没有使用泛型,也不建议从Presenter传递OnClickListener对象,而是建议我们的Presenter直接实现OnClickListener接口,这样做,EventHelper会自动帮我们完成类型的检查和监听的设置。
到这里,我们还有一个helper没有看实现,就是那个获取泛型类型的帮助类。
/**
* Created by www.maiziedu.com on 2015/11/15.
*/
public class GenericHelper {
public static <T> Class<T> getViewClass(Class<?> klass) {
Type type = klass.getGenericSuperclass();
if(type == null || !(type instanceof ParameterizedType)) return null;
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] types = parameterizedType.getActualTypeArguments();
if(types == null || types.length == 0) return null;
return (Class<T>) types[0];
}
}
这个类中仅仅一个方法,不过可能大部分人对这里面的代码非常陌生,这里做的事很直接,就是根据我们提供的class,来获取这个类实现的那个泛型的类型,打个比方,下面的代码获取到的就是java.lang.String,
class Child extends Super<String> {}
以上就是利用Android MVP框架的实现思想,实现自己MVP框架的具体方法和源码,总的来说,掌握了思路和方法后,实现起来还是不难的。如果大家在自己的MVP框架实现过程中,有更好的思路或方法,也欢迎补充分享。
相关文章:《Android React Native中如何封装使用原生UI组件》
相关推荐
总的来说,"Android MVP框架MVPExtend"为开发者提供了一种高效、可维护的Android应用开发模式,通过明确的角色分工,提高了代码的可读性和可测试性,降低了复杂项目的开发难度。对于大型或者团队协作的项目,使用MVP...
一键生成Android mvp代码框架,节约开发时间,全自动生成布局文件界面以及mvp的框架
在Android开发中,MVP(Model-View-Presenter)设计模式是一种常见的架构选择,它将业务逻辑、数据处理和用户界面进行了分离,提高了代码的可测试性和可维护性。在这个"Android MVP设计框架模板 之 漂亮ListView上拉...
在Android应用开发中,MVP(Model-View-Presenter)模式是一种常见的设计模式,它将业务逻辑、数据处理和用户界面进行了分离,提高了代码的可测试性和可维护性。本资料"Android MVP模式实现登录操作.zip"可能包含了...
Android MVP设计框架模板
基于 MVP 架构使用Android通用开发框架快速开发微博项目实战
总结,MVP框架是Android开发中的一个重要的设计模式,它有助于构建整洁、可测试的代码结构。熟练掌握MVP的使用,能让你的Android应用开发工作更加高效。在实践中不断优化和调整,你会发现MVP框架能为你的项目带来...
> - 开发中的顶级父类组件,如:SuperActivity,SuperFragment,SuperModel,SuperPresenter > - 网络当然也是必不可少,给 OkHttp 添加日志拦截器 LogInterceptor,添加请求头的拦截器 HeadersInterceptor ,还有一些...
对应我的博文 --Android MVP架构,下载资源的同学可以看一看我的博文khkhkhkhkhkhkhkhkhkhkhk
本篇文章将深入探讨MVP框架在Android开发中的应用。 **一、MVP模式介绍** MVP模式由三部分组成:Model(模型)、View(视图)和Presenter(呈现者)。在Android中: 1. **Model**:代表数据模型,负责处理数据的...
MVP 架构,提供一套开发标准(View,Data,Event)以及模板和工具类并规范代码。封装层级少,简单高效兼容性好。 OKHttp、UIL图片加载、ZXing二维码、沉浸状态栏、下载安装、自动缓存以及各种Base、Demo、UI、Util...
非常不错的mvp框架,该MVP框架模式demo主要展现MVP框架的基本原理,且使用泛型使得Presenter可以动态绑定和解绑View层接口对象,能让你快速理解MVP的工作原理,有用到的朋友可以下载下来看看!
android mvp架构dome,能快速的帮助android开发新手较快的上手mvp架构思想,并且应用到自己的项目中去, android mvp架构dome,能快速的帮助android开发新手较快的上手mvp架构思想,并且应用到自己的项目中去,
在MVP框架中,Model通常与后台服务、数据库、网络API等交互,获取或存储数据。开发者应确保Model的代码与视图和 presenter 完全解耦,以提高代码的复用性和测试性。 2. **View**: View层是用户界面,包含Activity、...
Android-ZBLibrary是一款专为Android开发者设计的MVP(Model-View-Presenter)快速开发框架,结合了优秀的UI组件,旨在提升开发效率和代码可维护性。MVP是一种设计模式,它将业务逻辑、界面展示和数据处理进行了明确...
在Android应用开发中,"Android主流框架RxJava+Retrofit+MVP" 是一套非常流行的架构组合,广泛应用于各类主流应用程序。这套框架结合了响应式编程的RxJava、网络请求库Retrofit以及Model-View-Presenter(MVP)设计...
**Android MVP 框架详解** 在Android应用开发中,Model-View-Presenter(MVP)模式是一种常见的设计模式,它有助于实现清晰的代码结构,提高可测试性和可维护性。`Android-BaseMVP-master` 是一个基于MVP模式构建的...
简单明了让你明白mvp架构,简单明了让你明白mvp架构简单明了让你明白mvp架构简单明了让你明白mvp架构简单明了让你明白mvp架构简单明了让你明白mvp架构简单明了让你明白mvp架构简单明了让你明白mvp架构
在"超好用的Android MVP框架"中,可能包含以下组件或特性: - **BasePresenter**: 一个基础Presenter类,提供通用的方法,如绑定和解绑View,确保生命周期管理。 - **BaseView**: 为View提供一个接口,定义...
MVP架构的Android开发框架,丰富的功能、简单的实现、详细的注释、规范的风格。OKHttp、UIL图片加载、ZXing二维码、沉浸状态栏、下载安装、自动缓存以及各种Base、Demo、UI、Util直接用。全新的手势,侧滑返回、全局...