Android學習探索之運用MVP設計模式實現項目解耦

前言:

    一直致力於提升開發效率下降項目耦合,今天想抽空學習一下MVP架構設計模式,學習一下如何運用到項目中。android

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列表的契約接口類IUserModelapp

public interface IUserModel {

    void loadUserEntities(IGetUserEntitiesListener listener);
}

一個實現IUserModel的實現類UserModelImplide

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 接口類oop

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代碼以下post

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 \nage:%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分層以及各層的職責與做用。

相關文章
相關標籤/搜索