MVP - 自己在项目中的使用方式

1. MVP简介


M就是model,里边放的是javabean;
V就是View,就是Activity、Fragment;
P就是Presenter;

2. 自己使用


全局需要定义:

定义BaseView、BasePresenter,BaseView是View的父类,BasePresenter是Presenter的父类;

举例:这里以请求HomeFragment的 BannerView轮播图数据为例,结构如下:
图片.png

由上图可以看出

1>:整个项目底部来回切换的多个fragment都是放在ui包下边的;

2>:自己手动新建一个contract包,定义HomeFragmentContract接口,在里边定义View继承BaseView,里边的方法用于给Activity或者Fragment回调;定义Presenter继承BasePresenter,里边的方法用于写具体的联网请求的逻辑代码,目的就是把具体联网请求的方法和给Activity、Fragment中提供的方法分开,达到最大程度解耦;

下边以home首页的fragment为例,定义4个包,分别是contract、model、view、presenter;

3. 具体分析


3.1:定义HomeFragmentContract接口,代码如下:

/**
 * Email: [email protected]
 * Created by JackChen 2018/4/8 17:34
 * Version 1.0
 * Params:
 * Description:  :Home主页面
*/
public interface HomeFragmentContract {

    //View(activity/fragment)继承,需要实现的方法
    interface View extends BaseView {
        //设置轮播图
        void setBanner(BannerView mBanner, List arrayList);
        void setOnclick(int position);
        void setMarqueeClick(int position);
        void setGridClick(int position);
        void setGridClickThird(int position);
        void setGridClickFour(int position);
        void setNewsList2Click(int position, String url);
        void setNewsList5Click(int position , String url);
    }

    //Presenter控制器
    interface Presenter extends BasePresenter {
        void setActivity(MainActivity activity);
        //初始化
        DelegateAdapter initRecyclerView(RecyclerView recyclerView);
        BaseDelegateAdapter initBannerAdapter();
        BaseDelegateAdapter initGvMenu();
        BaseDelegateAdapter initMarqueeView();
        BaseDelegateAdapter initTitle(String title);
        BaseDelegateAdapter initList1();
        BaseDelegateAdapter initList2();
    }

}

contract中需要做的事:

1>:写一个 View接口用于继承BaseView,View就指的是Activity、Fragment,里边写的方法就是Activity或者Fragment中所需要实现的方法名字;

2>:写一个 Presenter接口继承BasePresenter控制器,里边的方法就是具体的联网请求的方法;

3.2:自己定义一个 HomeFragmentPresenter,只实现 HomeFrgmentContract.Presenter,然后复写所有的方法,而不实现HomeFragmentContract.View,目的是让Activity或者Fragment实现,这里就是让HomeFragment实现HomeFragmentContract.View,然后实现具体方法:

1>:HomeFrgmentContract中的View下边的方法,是让Activity、Fragment中回调的方法;

2>:HomeFragmentContract中的 Presenter下边的方法,是在HomeFragmentPresenter中实现的方法,然后把具体的联网请求的数据都写到Presenter下边的方法,只需要返回数据的结果给Activity或者Fragment就可以;
具体代码如下:

/**
 * Email: [email protected]
 * Created by JackChen 2018/4/8 17:37
 * Version 1.0
 * Params:
 * Description:  HomeFragmentPresenter 
*/
public class HomeFragmentPresenter implements HomeFragmentContract.Presenter {

    private HomeFragmentContract.View mView;
    private CompositeSubscription mSubscriptions;
    private MainActivity activity;

    public HomeFragmentPresenter(HomeFragmentContract.View androidView) {
        this.mView = androidView;
        mSubscriptions = new CompositeSubscription();
    }

    @Override
    public void subscribe() {

    }


    @Override
    public void unSubscribe() {
        mSubscriptions.clear();
    }


    @Override
    public void setActivity(MainActivity activity) {
        this.activity = activity;
    }


    @Override
    public DelegateAdapter initRecyclerView(RecyclerView recyclerView) {
        //初始化
        //创建VirtualLayoutManager对象
        VirtualLayoutManager layoutManager = new VirtualLayoutManager(activity);
        recyclerView.setLayoutManager(layoutManager);

        //设置回收复用池大小,(如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 View)
        RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
        recyclerView.setRecycledViewPool(viewPool);
        viewPool.setMaxRecycledViews(0, 20);

        //设置适配器
        DelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager, true);
        recyclerView.setAdapter(delegateAdapter);
        return delegateAdapter;
    }


    /**
     * 设置轮播图数据
     * @return
     */
    @Override
    public BaseDelegateAdapter initBannerAdapter() {
        final List arrayList = new ArrayList<>();
        arrayList.add("http://bpic.wotucdn.com/11/66/23/55bOOOPIC3c_1024.jpg!/fw/780/quality/90/unsharp/true/compress/true/watermark/url/L2xvZ28ud2F0ZXIudjIucG5n/repeat/true");
        arrayList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1505470629546&di=194a9a92bfcb7754c5e4d19ff1515355&imgtype=0&src=http%3A%2F%2Fpics.jiancai.com%2Fimgextra%2Fimg01%2F656928666%2Fi1%2FT2_IffXdxaXXXXXXXX_%2521%2521656928666.jpg");
        //banner
        return new BaseDelegateAdapter(activity, new LinearLayoutHelper(), R.layout.view_vlayout_banner, 1, Constant.viewType.typeBanner) {
            @Override
            public void onBindViewHolder(BaseViewHolder holder, int position) {
                super.onBindViewHolder(holder, position);
                // 绑定数据
                BannerView mBanner = holder.getView(R.id.banner);
                mView.setBanner(mBanner,arrayList);
            }
        };
    }


    /**
     * 设置8宫格数据
     */
    @Override
    public BaseDelegateAdapter initGvMenu() {
        //menu
        // 在构造函数设置每行的网格个数
        final TypedArray proPic = activity.getResources().obtainTypedArray(R.array.find_gv_image);
        final String[] proName = activity.getResources().getStringArray(R.array.find_gv_title);
        final List images = new ArrayList<>();
        for(int a=0 ; a info1 = new ArrayList<>();
                info1.add("1.银卡惠,一款大家都在使用的产品,出售各种优惠劵!");
                info1.add("2.欢迎入住银卡惠app,让您财运亨通!");
                marqueeView.startWithList(info1);
                // 在代码里设置自己的动画
                marqueeView.setOnItemClickListener(new MarqueeView.OnItemClickListener() {
                    @Override
                    public void onItemClick(int position, TextView textView) {
                        mView.setMarqueeClick(position);
                    }
                });
            }
        };
    }

    @Override
    public BaseDelegateAdapter initTitle(final String title) {
        return new BaseDelegateAdapter(activity, new LinearLayoutHelper(), R.layout.view_vlayout_title, 1, Constant.viewType.typeTitle) {
            @Override
            public void onBindViewHolder(BaseViewHolder holder, int position) {
                super.onBindViewHolder(holder, position);
                holder.setText(R.id.tv_title, title);
            }
        };
    }

    @Override
    public BaseDelegateAdapter initList1() {
//        //item1 gird
//        final TypedArray list1_image = activity.getResources().obtainTypedArray(R.array.find_list1_image);
//        final String[] list1_title = activity.getResources().getStringArray(R.array.find_list1_title);
//        final List images = new ArrayList<>();
//        for(int a=0 ; a 0) {
                    HomeBlogEntity model = Constant.findNews.get(position);
                    holder.setText(R.id.tv_title, model.getTitle());
                    ImageView imageView = holder.getView(R.id.iv_logo);
                    ImageUtils.loadImgByPicassoError(activity, model.getImageUrl(), R.mipmap.image_default, imageView);
                    holder.setText(R.id.tv_time, model.getTime());
                    holder.getItemView().setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mView.setNewsList2Click(position,Constant.findNews.get(position).getUrl());
                        }
                    });
                } else {
                    ImageView imageView = holder.getView(R.id.iv_logo);
                    holder.setText(R.id.tv_title, "标题 ");
                    imageView.setImageResource(R.mipmap.image_default);
                    holder.setText(R.id.tv_time, "时间");
                }
            }
        };
    }


    /**
     * 豆瓣电影
     */
    @Override
    public BaseDelegateAdapter initList3() {
        final TypedArray list3_image = activity.getResources().obtainTypedArray(R.array.find_list3_image);
        final String[] list3_title = activity.getResources().getStringArray(R.array.find_list3_title);
        final String[] list3_title_price = activity.getResources().getStringArray(R.array.find_list3_title_price);
        final List images = new ArrayList<>();
        for(int a=0 ; a images = new ArrayList<>();
        for(int a=0 ; a 0) {
                    Log.e("TAG" , "if语句") ;
//                    HomeBlogEntity model = Constant.findBottomNews.get(position);
//                    holder.setText(R.id.tv_title, model.getTitle());
//                    ImageView imageView = holder.getView(R.id.iv_logo);
//                    ImageUtils.loadImgByPicassoError(activity, model.getImageUrl(), R.mipmap.image_default, imageView);
//                    holder.setText(R.id.tv_time, model.getTime());
//                    holder.getItemView().setOnClickListener(new View.OnClickListener() {
//                        @Override
//                        public void onClick(View v) {
//                            mView.setNewsList5Click(position,Constant.findBottomNews.get(position).getUrl());
//                        }
//                    });
                } else {
//                    Log.e("TAG" , "else语句") ;
                    ImageView imageView = holder.getView(R.id.iv_logo);
                    holder.setText(R.id.tv_title, "官方自营IPhone9 Plus ");
                    imageView.setImageResource(R.mipmap.test_iphone);
                    holder.setText(R.id.tv_time, "¥129999");
                    holder.getItemView().setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {   // Constant.findBottomNews.get(position).getUrl()
                            mView.setNewsList5Click(position,"");
                        }
                    });
                }
            }
        };
    }

}

3.3:model:用于存放BannerView轮播图的javabean数据;

3.4:view:定义fragment包,创建HomeFragment然后实现HomeFragmentContract.View,然后实现里边的方法;

1>:直接在HomeFragment中创建presenter对象,然后调用HomeFragmentPresenter中对应的方法来获取返回的数据,从而就可以在HomeFragment中利用返回的数据来填充BannerView页面的数据和其他控件的数据;
代码如下:

/**
 * Email: [email protected]
 * Created by JackChen 2018/4/9 10:06
 * Version 1.0
 * Params:
 * Description:
*/

public class HomeFragment extends BaseFragment implements View.OnClickListener , HomeFragmentContract.View {

    private MainActivity activity;
    private HomeFragmentContract.Presenter presenter = new HomeFragmentPresenter(this);

    @Bind(R.id.tv_title)
    TextView tvTitle;
    @Bind(R.id.recyclerView)
    RecyclerView recyclerView;

    /** 存放各个模块的适配器*/
    private List mAdapters;
    private BannerView mBanner;
//    private Realm realm;

    private static boolean isFirstEnter = true;
    private RefreshLayout refreshLayout;
    private Intent intent;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        activity = (MainActivity) context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if(activity!=null){
            activity = null;
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if(mBanner!=null){
            mBanner.pause();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if(mBanner!=null){
            mBanner.resume();
        }
    }



    @Override
    public void onDestroy() {
        super.onDestroy();
        restore();
        presenter.unSubscribe();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        presenter.subscribe();
    }

    @Override
    public void onClick(View v) {

    }

    @Override
    public int getContentView() {
        install();
        return R.layout.fragment_example_assign_default;  // base_recycler_view
    }

    @Override
    public void initView() {
        refreshLayout = (RefreshLayout) activity.findViewById(R.id.refreshLayout);
        mAdapters = new LinkedList<>();
//        initRealm();
        presenter.setActivity(activity);
        initRecyclerView();
        tvTitle.setText("首页");
//        activity.showToolBar();
    }



    private void initRecyclerView() {
      
    }

    /**
     * 设置轮播图数据
     */
    @Override
    public void setBanner(BannerView mBanner, List arrayList) {
        this.mBanner = mBanner;
        mBanner.setHintGravity(2);
        mBanner.setAnimationDuration(1000);
        mBanner.setPlayDelay(2000);
        mBanner.setHintPadding(0,0,0, SizeUtil.dip2px(activity,10));

        mBanner.setAdapter(new BaseBannerPagerAdapter(activity, arrayList));
    }


    @Override
    public void initListener() {

    }

    @Override
    public void initData() {
    }

    @Override
    public void setOnclick(int position) {

    }

    @Override
    public void setMarqueeClick(int position) {

    }

    @Override
    public void setGridClick(int position) {

    }

    @Override
    public void setGridClickThird(int position) {
   
        }
    }


    /**
     * 为您精选
     */
    @Override
    public void setGridClickFour(int position) {
  
        }
    }

    @Override
    public void setNewsList2Click(int position, String url) {

    }

    }
}


4. 总结


上边啰啰嗦嗦这么多,大家如果不是很清楚或者不是很理解的,也没有关系,可以不用看上边的,只需要把我下边的总结看懂就ok,照样也可以很好的把MVP用在项目中。

1>:整个项目涉及到Activity或者Fragment包是ui包,然后在ui包下边创建底部所有的fragment包,如home、cart、my,表示首页、购物车、我的;

2>:全局创建BaseView、BasePresenter;

3>:然后针对于home首页,在里边创建4个包,分别是contract、model、view、presenter;

对于contract,创建HomeFragmentContract接口,需要做两件事:

第一:定义View接口,继承BaseView,然后定义一些方法,View下的方法作用是给Activity或者Fragment回调的;

第二:定义Presenter接口,继承BasePresenter,然后定义一些方法,Presenter下的方法作用是写具体进行联网请求的代码,来获取网络返回的数据;

4>:定义HomeFragmentPresenter,实现HomeFragmentContract.Presenter,然后实现里边的方法,把每一个需要填充数据的控件,所需要调用的接口的联网请求都写到对应的方法中,然后调用V层的回调方法,用于返回数据给Activity或者Fragment;

5>:让HomeFragment实现 HomeFragmentContract.View,然后实现里边的方法,即就是V层中的方法,V层中的方法其实在P层中已经获取到了数据,这里只是通过回调接口把数据回传给Activity或者Fragment的即可,然后在HomeFragment中直接获取到数据后,就可以给所需要的控件去填充数据就ok;

5. 注意:


上边自己只是举了一个具体的应用场景,我要说的是其他的所有页面,不管是其他的Fragment或者是点击任何一个Fragment中的按钮或者点击任何地方的按钮进入某个Activity,都是可以使用上边的方式来处理数据,也就是说每一个小模块都需要创建对应4个包,分别是contract、model、view、presenter,然后在对应的包下创建对应的类,然后做对应的事情就ok。

以上就是自己在项目中MVP具体的使用方法,如果还不是特别清楚的,可以给我发私信,或者加我qq都是可以的

你可能感兴趣的:(MVP - 自己在项目中的使用方式)