前言:随着Android客户端的深入发展,Android客户端MVC开发模式中,View与Model层耦合严重,
导致拓展困难,多人协作的困难。如何让View与业务逻辑脱离开来。大神给出了MVP与MVVM解决方案。
随着web发展:
B/S :MVC架构
controller层使用struct,逻辑与view分开
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类臃肿。
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即可。