【Android MVP】实践与分析 2 ,使用父类与泛型实践MVP

本文探讨了在Android中如何通过MVP模式实现Activity和Fragment的优化,介绍了一个Presenter基类和通用View基类的使用,强调了MVP模式在应对业务变化和代码复用方面的优势。通过将逻辑与视图分离,MVP模式使得程序员能够更高效地管理和维护代码。

MVP模式
这里写图片描述

Presender 作为 View 与逻辑逻辑的桥梁

Android 模式中 Activity 实际上就是这个角色

ViewDelegate :view的代理。调用实例的view :xml,Linearlayout,自定view

如何使Activity 和 Fragment 成为优秀的 Presender

我定义了一下基类
Presender 基类,fragment与activity使用方法。
e.g

public abstract class BaseViewDelegateFragment<T extends BaseViewDelegate> extends Fragment {

    protected T mViewDelegate;

    public T getmViewDelegate() {
        return mViewDelegate;
    }

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        //因为没有使用框架,在此处初始化View.使用泛型,调用View的方法,给view赋予生命周期
        createViewDelegate();
        //给view设置逻辑调用
        mViewDelegate.setFragment(this);
        super.onCreate(savedInstanceState);
    }

    /**
     * 创建viewdelegate,并绑定到fragment
     */
    protected abstract void createViewDelegate();

    @Override
    public View onCreateView(LayoutInflater inflater
    , ViewGroup container, Bundle savedInstanceState) {
        //创建view并,给view赋值
        mViewDelegate.create(inflater, null, savedInstanceState);
        return mViewDelegate.create(inflater, null, savedInstanceState);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onViewCreated(view, savedInstanceState);
        mViewDelegate.initWidget();//初始化组件
        mViewDelegate.initListener();//初始化组件监听
    }

    /*****************
      *presender 给view赋值生命周期 
      *其实很少会用到。
      *一般都是presender 生命周期调用 view的方法
      **********************/
    @Override
    public void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
    }

    @Override
    public void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        mViewDelegate.onPause();
    }

    public void popBack() {
        mViewDelegate.hideSoftInputMethod();
        FragmentUtil.popBackImmediate(getActivity());
    }

}

通用的View基类,适用与用户交互时候用

public abstract class BaseViewDelegate <P extends BaseViewDelegateFragment> implements IViewDelegate {

    /*************** INPUT METHOD **************************/
    InputMethodManager imm;

    /***************** 组件view ********************************************/
    protected final SparseArray<View> mViews = new SparseArray<View>();//保存view的容器类
    protected View rootView;//最外层的view

    public abstract int getRootLayoutId();

    /********** PRESENDER *************/
    protected P mFragment;

    public void setFragment(P mFragment) {
        this.mFragment = mFragment;
    }

    @Override
    public void create(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        int rootLayoutId = getRootLayoutId();
        rootView = inflater.inflate(rootLayoutId, container, false);
    }

    @Override
    public int getOptionsMenuId() {
        return 0;
    }

    //一些presender生命周期,不建议使用,但是用暂停handler很有效,
    //建议直接在presender生命周期,调用一些view的功能
    public void onCreate() {
    }
    public void onResume() {
    }

    @Override
    public View getRootView() {
        return rootView;
    }

    public void setRootView(View rootView) {
        this.rootView = rootView;
    }

    @Override
    public void initWidget() {
    //查找控件
    }

    @Override
    public void initListener() {
    //给控件设置监听
    }

    //查找控件
    public <T extends View> T findView(int id) {
        T view = (T) mViews.get(id);
        if (view == null) {
            view = (T) rootView.findViewById(id);
            mViews.put(id, view);
        }
        return view;
    }

    public <T extends View> T findView(String tag) {
        return this.rootView != null ? (T) this.rootView.findViewWithTag(tag) : null;
    }

使用的demo
fragment


public class SearchIndex extends BaseViewDelegateFragment<SearchIndexViewDelegate> {

    // 逻辑类
    protected Biz mBiz;//逻辑可以多个,presender里面初始化
    protected ShopBiz mShopBiz;//放一些对view数据的操作
    //主要是让view与数据交互.校验数据
    protected ShopDao mDao;

    public SearchIndex() {
    }

    /***获取逻辑****/
    public SupplierStoreItemViewDecorate getStoreBiz() {
        return mShopbiz;
    }

    @Override
    protected void createViewDelegate() {
        // TODO Auto-generated method stub
        mViewDelegate = new SearchIndexViewDelegate();//初始化view
        mStoreBiz = new ShopBiz();//初始化View逻辑
        mDao = new ShopDao;//数据库操作
    }

    @Override
    public void initData(Bundle savedInstanceState, View... view) {
        // TODO Auto-generated method stub
        super.initData(savedInstanceState, view);
        initHotSearchData();
        //请求网络操作,属于逻辑,由于网络通常需要异步回调,回调建议直接纺织到presender里面
    }

    /** 初始化热门搜索 */
    public void initHotSearchData() {
        //网络请求回调
    JsonUtil.request(this, URLS.supplyHotProductList, "", new HttpModelJsonCallBack() {
            @Override
            public void onSuccess(HttpModel model) {
                // view 刷新
    mViewDelegate.reflashHotSearchView(model.genPageList(SupplierCommodityModel.class));
            }
        });
    }


    /** 添加历史 */
    public void addHistotry(SupplierCommodityModel model) {
        mDao.addHistory(model);
    }


    /***
     * 清空历史记录
     **/
    public void clearHistory() {
        mDao.clearHistory(new OnBackUpdateData() {

            @Override
            public void updata(Object... obj) {
                // TODO Auto-generated method stub
                mViewDelegate.reflashClearHistoryView();

            }
        });
    }



    /** 跳转到商品详情 */
    public void toCommodity(SupplierCommodityModel item) {
        // TODO Auto-generated method stu
        mViewDelegate.hideSoftInputMethod();
        FragmentUtil.switchFragment(getActivity(), this, new SearchCommodityResult(item, mtype));
    }

}

view 部分


public class SearchIndexViewDelegate extends BaseViewDelegate<SearchIndex> implements OnClickListener {

    /********** DECLARES *************/
    protected LinearLayout sl_hot_search_parent_ll; // 热门搜索父view
    protected android.support.v7.widget.RecyclerView sl_hot_search_rv; // 热搜view
    protected TextView sl_hint_text_tv; // 历史数据标题
    protected ListView sl_content_lv; // 历史数据显示
    protected EditText sil_search_text_et; // titlebar搜索栏
    protected TextView sil_right_tv; // titlebar右边按钮
    protected TextView sil_search_selector_tv; // 搜索项选择

    /********** ADAPTER *************/
    protected BaseAdapter<SupplierCommodityModel> mSearchCommodityAdapter;
    protected BaseAdapter<SupplyStoreInfo> mSearchShopAdapter;
    protected BaseAdapter<SupplierCommodityModel> mHistoryAdapter;
    protected BaseRecycleViewAdapter<SupplierCommodityModel> mHotSearchAdapter;
    protected BaseAdapter<DropDownSelectModel> mSearchTypeAdapter;

    /*************** POPWIN **********************/
    protected PopupWindow mSearchTypePopWin; // 搜索项选择Popwin

    @Override
    public int getRootLayoutId() {
        // TODO Auto-generated method stub
        return R.layout.search_indext_layout;
    }

    @Override
    public void initWidget() {
        // TODO Auto-generated method stub
        super.initWidget();
        sl_hot_search_parent_ll = findView(R.id.sl_hot_search_parent_ll);
        sl_hot_search_rv = findView(R.id.sl_hot_search_rv);
        sl_hint_text_tv = findView(R.id.sl_hint_text_tv);
        sl_content_lv = findView(R.id.sl_content_lv);
        sil_search_text_et = findView(R.id.sil_search_text_et);
        sil_right_tv = findView(R.id.sil_right_tv);
        sil_search_selector_tv = findView(R.id.sil_search_selector_tv);

        // 初始化页面适配
        initAdapter();
    }

    protected void initAdapter() {
        initSearchTypeAdapter(); // 搜索项适配器
        initSearchCommodityAdapter(); // 搜索商品适配器
        initSearchShopAdapter(); // 搜索商品适配器
        initHotSearchAdapter(); // 热搜适配器
        initHistoryAdapter();// 历史适配器
    }

    /*************** 搜索索引初始化 **************************/
    protected void initSearchTypeAdapter() {

        mSearchTypeAdapter = new BaseAdapter<DropDownSelectModel>(getActivity(), mFragment.getSearchTypeData(),
                R.layout.drop_down_black_popwin_item) {
            @Override
            public void showViewData(View convertView, DropDownSelectModel item, int position) {
                // TODO Auto-generated method stub
                super.showViewData(convertView, item, position);
                ViewHolder.setImage(convertView, R.id.icon_iv,
                        item.drawableId == 0 ? R.drawable.vegetable_dropdown_select : item.drawableId);
                ViewHolder.setText(convertView, R.id.name_tv, item.name);
            }

        };
        DropDownSelectModel model = mSearchTypeAdapter.getItem(0);
        sil_search_selector_tv.setText(model.name);
        mFragment.setSearchTypeModel(model);
    }

    /********* 初始化搜索商品 *************/
    protected void initSearchCommodityAdapter() {
        mSearchCommodityAdapter = new BaseAdapter<SupplierCommodityModel>(getActivity(), null,
                R.layout.search_history_list_item) {

            @Override
            public void showViewData(View convertView, SupplierCommodityModel item, int pos) {
                // TODO Auto-generated method stub
                TextView textView = ViewHolder.setText(convertView, R.id.shli_history_tv, item.name);
                textView.setCompoundDrawables(null, null, null, null);
            }
        };
    }

    /*********** 初始化搜索店铺 **************/
    protected void initSearchShopAdapter() {
        // TODO Auto-generated method stub
        mSearchShopAdapter = new BaseAdapter<SupplyStoreInfo>(getActivity(), null,
                R.layout.search_store_reslut_list_item) {

            @Override
            public void showViewData(View convertView, SupplyStoreInfo item, int position) {
                // TODO Auto-generated method stub
                super.showViewData(convertView, item, position);
                mFragment.getStoreBiz().setmModel(item);
                mFragment.getStoreBiz().showState(ViewHolder.getText(convertView, R.id.ssri_state_tv));
                mFragment.getStoreBiz().showHead(ViewHolder.getImg(convertView, R.id.ssri_icon_iv));
                mFragment.getStoreBiz().showStoreName(ViewHolder.getText(convertView, R.id.ssri_name_tv));
            }
        };
    }

    /** 初始化历史 ***/
    protected void initHistoryAdapter() {
        mHistoryAdapter = new BaseAdapter<SupplierCommodityModel>(getActivity(), null,
                R.layout.search_history_list_item) {

            @Override
            public void showViewData(View convertView, SupplierCommodityModel item, int pos) {
                // TODO Auto-generated method stub
                TextView textView = ViewHolder.setText(convertView, R.id.shli_history_tv, item.name);
                int lastpos = mHistoryAdapter.getCount() - 1;
                if (pos == lastpos) {
                    textView.setGravity(Gravity.CENTER);
                    textView.setCompoundDrawables(null, null, null, null);
                } else {
                    textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
                    textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.time_tag, 0, 0, 0);
                }
            }
        };

        sl_content_lv.setAdapter(mHistoryAdapter);

    }

    /************* 初始化热搜 ***************/
    protected void initHotSearchAdapter() {

        mHotSearchAdapter = new BaseRecycleViewAdapter<SupplierCommodityModel>(getActivity(), null,
                R.layout.search_hot_list_item) {

            @Override
            public void showViewData(RecycleViewHolder rvHolder, final int pos) {
                super.showViewData(rvHolder, pos);

                // TODO Auto-generated method stub
                rvHolder.setText(R.id.shli_hot_tv, mHotSearchAdapter.getItem(pos).productName);
                rvHolder.setOnItemClickListner(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        mFragment.toCommodity(mHotSearchAdapter.getItem(pos));
                    }
                });
            }
        };
        // recycleview设置横向滚动
        LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
        mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        sl_hot_search_rv.setLayoutManager(mLayoutManager);
        sl_hot_search_rv.setHasFixedSize(true);
        sl_hot_search_rv.setAdapter(mHotSearchAdapter);

    }

    @Override
    public void initListener() {
        // TODO Auto-generated method stub
        super.initListener();
        TextWatcher textWatcher = new BaseTextWatch() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // TODO Auto-generated method stub
                super.onTextChanged(s, start, before, count);
                if (s.length() == 0) { // 根据输入,自动显示历史记录
                    mFragment.initHistoryData();
                }
            }
        };

        OnItemClickListener onItemClickListener = new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ListAdapter ladapter = sl_content_lv.getAdapter();

                if (ladapter == mHistoryAdapter && position == ladapter.getCount() - 1) {
                    // 历史记录点击
                    mFragment.clearHistory();
                } else {
                    // 其他搜索记录点击
                    Object obj = ladapter.getItem(position);

                    if (ladapter == mSearchCommodityAdapter) {
                        // 商品记录搜索点击
                        mFragment.addHistotry((SupplierCommodityModel) obj);// 添加历史
                        mFragment.toCommodity((SupplierCommodityModel) obj);// 跳转到搜索商品结果页面
                    } else if (ladapter == mSearchShopAdapter) {
                        // 店铺记录搜索点击
                        mFragment.toShopResult((SupplyStoreInfo) obj);// 跳转到店铺详情
                    } else {// 历史记录
                        mFragment.toCommodity((SupplierCommodityModel) obj);// 跳转到搜索商品结果页面
                    }
                }
            }
        };

        OnKeyListener onKeyListener = new OnKeyListener() {

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // TODO Auto-generated method stub
                if (keyCode == KeyEvent.KEYCODE_ENTER) {
                    // 修改回车键功能,立刻搜索
                    mFragment.search(sil_search_text_et.getText().toString());
                    // 先隐藏键盘
                    hideSoftInputMethod();
                    return true;
                }
                return false;
            }
        };



        sil_right_tv.setOnClickListener(this);
        sil_search_text_et.addTextChangedListener(textWatcher);
        sl_content_lv.setOnItemClickListener(onItemClickListener);
        sil_search_text_et.setOnKeyListener(onKeyListener);
        sil_search_selector_tv.setOnClickListener(this);
        // 设置搜索栏状态
        initSearchState();
    }

    protected void initSearchState() {
        // TODO Auto-generated method stub
        sil_search_text_et.requestFocus();
        toggleSoftInputMethod();
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case R.id.sil_right_tv:// titlebar右边按钮
            mFragment.popBack();
            break;
        case R.id.sil_search_selector_tv:// titlebar 左边下拉框
            showDropDownPopWindow(); // 显示下拉的选择框框
            break;
        default:
            break;
        }
    }

    /********* 初始化下拉选项 ***********************/
    protected void showDropDownPopWindow() {
        // TODO Auto-generated method stub
        if (null == mSearchTypePopWin) {
            mSearchTypePopWin = PopWindowBuilder.dropDownBlackPopWindowBuilder(getActivity(), mSearchTypeAdapter,
                    new OnItemClickListener() {

                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                            DropDownSelectModel model = mSearchTypeAdapter.getItem(position);
                            mFragment.setSearchTypeModel(model); // 逻辑配置
                            sil_search_selector_tv.setText(model.name);// 显示选中搜索项
                            mSearchTypePopWin.dismiss();// 隐藏dialog
                        }

                    });
        }

        mSearchTypePopWin.showAsDropDown(sil_search_selector_tv);
    }

    /***************** reflash view **********************/

    /*********** 刷新商品名称结果记录 ***********************/
    public void reflashSearchCommodityResultView(List<SupplierCommodityModel> list) {
        sl_hot_search_parent_ll.setVisibility(View.GONE); // 隐藏热搜
        sl_hint_text_tv.setText(NullUtils.isEmptyList(list) ? "没有搜索结果" : "搜索结果");

        // 设置为搜索适配
        sl_content_lv.setAdapter(mSearchCommodityAdapter);
        mSearchCommodityAdapter.setLists(list);
        mSearchCommodityAdapter.notifyDataSetChanged();
    }

    /*********** 刷新店铺结果记录 ***********************/
    public void reflashSearchShopResultView(List<SupplyStoreInfo> list) {
        sl_hot_search_parent_ll.setVisibility(View.GONE); // 隐藏热搜
        sl_hint_text_tv.setText(NullUtils.isEmptyList(list) ? "没有搜索结果" : "搜索结果");

        // 设置为搜索适配
        sl_content_lv.setAdapter(mSearchShopAdapter);
        mSearchShopAdapter.setLists(list);
        mSearchShopAdapter.notifyDataSetChanged();
    }

    /*********** 刷新历史记录 ***********************/
    public void reflashHistoryView(List<SupplierCommodityModel> list) {
        sl_hot_search_parent_ll.setVisibility(View.VISIBLE); // 显示热搜
        sl_hint_text_tv.setVisibility(View.VISIBLE); // 显示历史搜索标题

        // 设置为历史适配
        mHistoryAdapter.setLists(list); // 重设历史记录
        sl_content_lv.setAdapter(mHistoryAdapter);
        mHistoryAdapter.notifyDataSetChanged();
        mHotSearchAdapter.notifyDataSetChanged();
    }

    /************ 清空历史 ****************/
    public void reflashClearHistoryView() {
        mHistoryAdapter.clearLists(); // 清除历史view数据
        mHistoryAdapter.notifyDataSetChanged();
    }

    /************* 刷新热搜 *************************/
    public void reflashHotSearchView(List<SupplierCommodityModel> list) {
        mHotSearchAdapter.setLists(list);
        mHotSearchAdapter.notifyDataSetChanged();
    }

    /************* 生命周期调用 *******************/
    @Override
    public void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        if (null == mSearchTypePopWin) {
            PopupWindowUtil.dismiss(mSearchTypePopWin);
        }
    }

}

写到此处。我想总结一些一下为何,使用mvp模式
用户操作页面经常需要根据业务不断改变。
作为程序员,又不想做重复造轮子的工作。
mvp模式,使具体业务逻辑与具体view分离。
方便了程序员优化代码。
业务逻辑,与view可以分别抽取代码。以便复用。

有些同志问,为何不一开始写一个自定义view来使用了。
时常做前端开发的程序员,或许更明白。具体业务view更多的是组合使用。
自定义view更多的是抽象抽取的组件。
多个自定义view组件=》具体业务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值