Android MVP 实践 Dagger + activity/fragment + viewDelegate

前言:随着Android客户端的深入发展,Android客户端MVC开发模式中,View与Model层耦合严重,
导致拓展困难,多人协作的困难。如何让View与业务逻辑脱离开来。大神给出了MVP与MVVM解决方案。

MVC:
C/S :
Android MVP 实践 Dagger + activity/fragment + viewDelegate_第1张图片

随着web发展:
B/S :MVC架构
controller层使用struct,逻辑与view分开
Android MVP 实践 Dagger + activity/fragment + viewDelegate_第2张图片

C/S:MVP
Android MVP 实践 Dagger + activity/fragment + viewDelegate_第3张图片

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 【[email protected]】
     * @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即可。

你可能感兴趣的:(Android MVP 实践 Dagger + activity/fragment + viewDelegate)