zoukankan      html  css  js  c++  java
  • Android学习探索之运用MVP设计模式实现项目解耦

    前言:

        一直致力于提高开发效率降低项目耦合,今天想抽空学习一下MVP架构设计模式,学习一下如何运用到项目中。

    MVP架构设计模式

       MVP模式是一种架构设计模式,也是一种经典的界面模式。MVP中的M代表Model, V是View, P是Presenter。

    • Model 业务逻辑和实体模型 
    • View 代表对应布局文件以及一个将UI界面提炼而抽象出来的接口。 
    • Presenter Model和View之间的桥梁

    为什么采用MVP

    • 降低耦合度
    • 模块职责划分明显
    • 利于测试驱动开发
    • 代码复用
    • 隐藏数据
    • 代码灵活性

     举个栗子说明一下

      先看下整个栗子的结构示意图

    1)首先我们先看M层

    Model代表业务逻辑和实体模型,栗子中的M层包含一个实体类UserEntity,具体代码如下:

    public class UserEntity {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }

    一个获取user列表的契约接口类IUserModel

    public interface IUserModel {
    
        void loadUserEntities(IGetUserEntitiesListener listener);
    }

    一个实现IUserModel的实现类UserModelImpl

    public class UserModelImpl implements IUserModel {
        @Override
        public void loadUserEntities(final IGetUserEntitiesListener listener) {
            //模拟网络请求数据过程
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    List<UserEntity> userModels = new ArrayList<>();
                    int testCount = 20;
                    for (int i = 0; i < testCount; i++) {
                        UserEntity userModel = new UserEntity();
                        userModel.setAge(i * 5);
                        userModel.setName(String.format("李%d", i));
                        userModels.add(userModel);
                    }
                    listener.onGetUserEntities(userModels);
                }
            }, 3000);
        }
    }

    回调结果的IGetUserEntitiesListener 接口类

    public interface IGetUserEntitiesListener {
    
        void onGetUserEntities(List<UserEntity> userEntities);
    
    }

    2)V层就是页面的展示与加载

    这里的V层为一个接口契约类和Activity,负责View的绘制以及与用户交互,首先看下契约接口类

    public interface ILoadDataView<T> {
    
        void startLoading();//开始加载
    
        void loadFailed();//加载失败
    
        void loadSuccess(List<T> list);//加载成功
    
        void finishLoading();//结束加载
    
    }

     Activity代码如下

    public class MainActivity extends AppCompatActivity implements ILoadDataView<UserEntity> {
        private MyAdapter mMyAdapter;
        private ProgressDialog mProgressDialog;
        private LoadUserEntitiesPresenter mLoadListPresenter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initViews();
        }
    
        private void initViews() {
            ListView testListView = (ListView) findViewById(R.id.test_listView);
            mMyAdapter = new MyAdapter(this);
            testListView.setAdapter(mMyAdapter);
            mLoadListPresenter = new LoadUserEntitiesPresenter(this);
            findViewById(R.id.test_button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mMyAdapter.removeDatas();
                    mMyAdapter.notifyDataSetChanged();
                    mLoadListPresenter.loadUserEntities();
                }
            });
        }
    
        @Override
        public void startLoading() {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("正在加载中");
            mProgressDialog.show();
        }
    
        @Override
        public void loadFailed() {
    
        }
    
        @Override
        public void loadSuccess(List<UserEntity> list) {
            mMyAdapter.addDatas(list);
            mMyAdapter.notifyDataSetChanged();
        }
    
        @Override
        public void finishLoading() {
            if (mProgressDialog != null) {
                mProgressDialog.dismiss();
                mProgressDialog = null;
            }
        }

    3)P层负责完成View于Model间的交互,由P分别操作M层和V层,是他们之间的桥梁

     首先看下Presenter的实现,包括一个ILoadUserEntitiesPresenter契约接口类和LoadUserEntitiesPresenter实现类

    ILoadUserEntitiesPresenter类代码

    public interface ILoadUserEntitiesPresenter {
    
        void loadUserEntities();
    
    }
    LoadUserEntitiesPresenter实现类
    public class LoadUserEntitiesPresenter implements ILoadUserEntitiesPresenter {
        private ILoadDataView<UserEntity> mILoadListView;
        private IUserModel mUserModel;
    
        public LoadUserEntitiesPresenter(ILoadDataView<UserEntity> mILoadListView) {
            this.mILoadListView = mILoadListView;
            this.mUserModel = new UserModelImpl();
        }
    
        @Override
        public void loadUserEntities() {
            mILoadListView.startLoading();
            mUserModel.loadUserEntities(new IGetUserEntitiesListener() {
                @Override
                public void onGetUserEntities(List<UserEntity> userEntities) {
                    if (userEntities != null && !userEntities.isEmpty()) {
                        mILoadListView.loadSuccess(userEntities);
                    } else {
                        mILoadListView.loadFailed();
                    }
                    mILoadListView.finishLoading();
                }
            });
        }
    }

    为了保证栗子能够正常运行,顺便贴出其他的代码

    public class MyAdapter extends BaseAdapter {
        private List<UserEntity> mUserModels;
        private Context mContext;
    
        public MyAdapter(Context mContext) {
            this.mContext = mContext;
            this.mUserModels = new ArrayList<>();
        }
    
        @Override
        public int getCount() {
            return mUserModels != null ? mUserModels.size() : 0;
        }
    
        @Override
        public Object getItem(int position) {
            return mUserModels.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                viewHolder = new ViewHolder();
                convertView = viewHolder.bindVIew();
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.bindData(position);
            return convertView;
        }
    
        public void addDatas(List<UserEntity> modelList) {
            if (modelList == null || modelList.isEmpty()) {
                return;
            }
            mUserModels.addAll(modelList);
        }
    
        public void removeDatas() {
            mUserModels.clear();
        }
    
        public class ViewHolder {
    
            private TextView mTextView;
    
            public View bindVIew() {
                View convertView = LayoutInflater.from(mContext).inflate(R.layout.item_listview, null);
                mTextView = (TextView) convertView.findViewById(R.id.test_textview);
                return convertView;
            }
    
            public void bindData(int position) {
                UserEntity userModel = mUserModels.get(position);
                mTextView.setText(String.format("name:%s 
    age:%d", userModel.getName(), userModel.getAge()));
            }
        }
    
    }
    MyAdapter
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.whoislcj.testmvp.MainActivity">
    
        <Button
            android:id="@+id/test_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:text="测试mvp"/>
    
        <ListView
            android:id="@+id/test_listView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    
    </LinearLayout>
    activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/test_textview"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:minHeight="50dp"
              android:layout_margin="10dp"
              android:background="@android:color/white"
              android:gravity="center"
              android:orientation="vertical"
              android:textColor="@android:color/black"
              android:textSize="16sp"/>
    item_listview.xml

    总结:

     这里仅仅就是MVP的简单实现,为了方便简单的认识MVP分层以及各层的职责与作用。

  • 相关阅读:
    如何心无旁鹜的编程
    [转]虚拟现实和现实增强技术带来的威胁
    Mac上好用软件集锦
    无论如何都要来报到
    Unity3D脚本语言UnityScript初探
    X3DOM新增剪裁平面节点ClipPlane支持
    用Perl编写Apache模块续二
    如何浪费自己青春
    macbook 我们需要买吗
    看了一本Unity3D的教程
  • 原文地址:https://www.cnblogs.com/whoislcj/p/6646925.html
Copyright © 2011-2022 走看看