Android(安卓)MVP 实践 Dagger + activity/fragment + viewDelegate
前言:随着Android客户端的深入发展,Android客户端MVC开发模式中,View与Model层耦合严重,
导致拓展困难,多人协作的困难。如何让View与业务逻辑脱离开来。大神给出了MVP与MVVM解决方案。
MVC:
C/S :
随着web发展:
B/S :MVC架构
controller层使用struct,逻辑与view分开
C/S:MVP
C/S的MVC代码:
耦合严重的代码
/** * 加载左边菜单 */ public void loadLeftMenu(final String mCatpid) { mPreLoadingView.showProcess(); lv_menu.setVisibility(View.GONE); AjaxParams params = new AjaxParams(); Map map = new HashMap(); map.put("catpid", mCatpid); map.put("token", MyApp.getInstance().token); params.put("reqJson", AESEncryption.superEncrypt(ResolveJsonUtils.ObjectToJson(map))); FinalHttp fh = new FinalHttp(); fh.post(RequestURL.categoryListUrl, params, new MyAjaxCallBack() { @Override public void onFailure(Throwable t, int errorNo, String strMsg) { // TODO Auto-generated method stub super.onFailure(t, errorNo, strMsg); showMessage(getString(R.string.request_failure)); mPreLoadingView.showNetFail(new View.OnClickListener() { @Override public void onClick(View v) { loadLeftMenu(mCatpid); } }); } @Override public void onLoadSuccess(AllResponseInfo responseInfo) { // System.out.println("result-->"+result); // 成功获取数据 if (responseInfo.success) { li_menu = ResolveJsonUtils.getModelArray( ResolveJsonUtils .ObjectToJson(responseInfo.obj), ProductTypeMenuInfo.class); if (li_menu != null && li_menu.size() > 0) { if (menuAdapter == null) { menuAdapter = new ProductLeftMenuAdapter( activity, li_menu); } lv_menu.setAdapter(menuAdapter); // 加载内容 loadNetWorkContentData(true, false, false); lv_menu.setVisibility(View.VISIBLE); mPreLoadingView.hideWait(); } else {// 没有列表数据 mPreLoadingView.showEmptyState(R.string.state_no_good); } } else {// 没有列表数据 showMessage(responseInfo.msg); mPreLoadingView.showEmptyState(R.string.state_no_good); } } }); }
逻辑和数据耦合在一起处理,由于View需要不断的迭代。逻辑的拓展。导致,Activity类臃肿。
MVP模式=》
Activity/Fragment专注实现Presender的职责。
ViewDelegate专注View的职责。
Dagger Android端的Spring ioc,反转控制框架
Activity/Fragment 注入ViewDelegate
ViewDelegate注入fragment
实现Presender与view的互动
View端
public class HomeFragmentViewDalegate extends FragmentViewDelegate { @Inject UserBiz mUserBiz;//登录校验组件 @Inject HomeFragment mHomeFragment; @Inject public HomeFragmentViewDalegate() { //注入HomeFragmentViewDalegate到对象图里面 } @Override public void initWidget() { super.initWidget(); et_search = get(R.id.et_search); viewPager = get(R.id.viewPager); dot_layout = get(R.id.dot_layout); // 初始化头部滚动图片 initTopView(); // 初始化第一层菜单 initFirstMenu(); // 初始化第二层菜单 initSecondMenu(); // 初始化第三层菜单 initThirdMenu(); } /** * @method 初始化滚动图片 * @author Island_gyy 【island_yy@qq.com】 * @date 2016/6/27 11:09 * @describe */ private void initTopView() { topViewAdapter = new CyclePagerAdapter(getActivity(), mHomeFragment.getTopImage());//通过Prsender获得数据 viewPager.setAdapter(topViewAdapter); // 增加page监听 initPageListener(); // 初始化dot(就是下面那几个点) initDots(); //启动计数器 initTimer(); }}
prsender端
public class HomeFragment extends MyBaseFragment { @Inject HomeFragmentViewDalegate mViewDalegate;//注入view /**逻辑操作**/ private List li_topImage; // 第一层菜单 private List li_menu; // 第三层菜单 private List li_bottomMenu; //数据库操作 private DataBaseTool dbTool; //配置activity注入 private void initDagger() { HomeFragmentComponent d = DaggerHomeFragmentComponent.builder() .globalComponent(MyApp.getInstance().getGlobalComponent()) .homeFragmentModule(new HomeFragmentModule(this)).build(); d.inject(this); mViewDalegate.setRootView(rootView);//把view赋值给viewdalegate } //初始化操作 public void init(Bundle savedInstanceState, View... view) { // TODO Auto-generated method stub initDagger(); } // 初始化头部滚动图片 public List getTopImage() { // 头部图片的list li_topImage = new ArrayList(); String savePath = ConfigUtils.getString(activity, ConfigConstant.saveHomeTopImagePath, ""); if (!TextUtils.isEmpty(savePath)) { List li_path = ResolveJsonUtils.getModelArray( savePath, GuidImgInfo.class); if (li_path != null) { li_topImage.addAll(li_path); } else { li_topImage.add(new GuidImgInfo("-1")); li_topImage.add(new GuidImgInfo("-1")); } } else { li_topImage.add(new GuidImgInfo("-1")); li_topImage.add(new GuidImgInfo("-1")); } if (MyApp.getInstance().userInfo != null) { // 获取顶部轮播图 getGuidImgList(); } return li_topImage; }
这样就完成了view的分离
后记:有人会提问为何使用Dagger2框架,不使用。直接的,setter注入呢?
增加开发效率、省去重复的简单体力劳动
首先new一个实例的过程是一个重复的简单体力劳动,dagger2完全可以把new一个实例的工作做了,因此我们把主要精力集中在关键业务上、同时也能增加开发效率上。
省去写单例的方法,并且也不需要担心自己写的单例方法是否线程安全,自己写的单例是懒汉模式还是饿汉模式。因为dagger2都可以把这些工作做了。
更好的管理类实例
每个app中的ApplicationComponent管理整个app的全局类实例,所有的全局类实例都统一交给ApplicationComponent管理,并且它们的生命周期与app的生命周期一样。
每个页面对应自己的Component,页面Component管理着自己页面所依赖的所有类实例。
因为Component,Module,整个app的类实例结构变的很清晰。
解耦
假如不用dagger2的话,一个类的new代码是非常可能充斥在app的多个类中的,假如该类的构造函数发生变化,那这些涉及到的类都得进行修改。设计模式中提倡把容易变化的部分封装起来。
我们用了dagger2后。
假如是通过用Inject注解标注的构造函数创建类实例,则即使构造函数变的天花乱坠,我们基本上都不需要修改任何代码。
假如是通过工厂模式Module创建类实例,Module其实就是把new类实例的代码封装起来,这样即使类的构造函数发生变化,只需要修改Module即可。
更多相关文章
- No.11 使用firewall配置的防火墙策略的生效模式
- 【转】Android(安卓)JNI实例
- Android视频解码及渲染
- 细数Android原生工程接入EasyAR-SurfaceTracking遇到的坑
- android中自带的开发模板
- Android零基础入门第77节:Activity任务栈和启动模式
- Android编程心得---ViewPager+Fragment篇(一)初始化ViewPager的一
- Android开发自动生成的AndroidManifest.xml中的allowBackup属性
- Android(安卓)常用设计模式(二) -- 单例模式(详解)