Android设计模式之 MVP和泛型结合

来源:互联网 发布:mac发布会时间 编辑:程序博客网 时间:2024/04/19 04:50

什么是MVP?

MVP设计模式有大量的的博客去讲解,我今天还是要讲讲什么是MVP模式因为想让自己有个更加深刻理解,再加上自己最近看了项目发现和Java中的泛型结合可以让整个MVP模式代码更加优雅和简洁,好了现在说正题了MVP.
M:数据提供层:Model 一般由请求网络类或者数据库等组成。
V :数据展示层:View activity,fragment组成
P:业务逻辑层:Presenter 处理Model View之间逻辑代码组成

MVP关系图:

这里写图片描述
上面的图已经很好说明Model View Presenter 三者之间的关系我就不都说了
讲讲T-MVP肯定要用举例子才更好理解它,那我就用登录这个功能来讲讲MVP模式吧!
目录结构

这里写图片描述

我们来看下基类包中
首先baseModel接口
这里写图片描述
可以看到并没有任何代码 由于这个小项目所以一部涉及 Model 抽取
BasePresenter类

  public abstract  class BasePresenter <V,M>{    public  V  mView;    public M mModel;    public void  setVM(V view,M modle){        this.mView=view;        this.mModel=modle;    }}

BaseView接口

 public interface BaseView {    //请求开始调用    void RequstStart();    //请求结束调用    void ReqeustEnd();    //网络错误的方法    void onInternetError();    //请求错误的方法    void ReqeustError();}

看完MVP基类 , 发现在Presenter 会有二元组泛型 这个就是泛型和MVP结合精华所在,
现在再看BaseActivity

  public abstract  class BaseActivity<P extends BasePresenter,M extends BaseModel > extends AppCompatActivity implements BaseView {    public  P mPresenter;    public  M  mBaseModel;    public Activity mActivity;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(getContentView());        System.out.println("BaseActivity.onCreate");        mPresenter= CommUtils.getT(this,0);        mBaseModel=CommUtils.getT(this,1);        if(this instanceof  BaseView){            mPresenter.setVM(this,mBaseModel);        }        mActivity=this;        init();        initView();        initData();    }    /**     * 初始化变量     */    public  abstract  void init();    /**     * 初始化控件     */    public abstract void initView();    /**     * 初始化数据     */    public  abstract  void initData();    /**     * 获得activity布局文件     * @return     */    public abstract int getContentView();}

介绍完基类就来看 具体实现吧

/** * Created by Administrator on 2016/12/14. * 管理登录接口类  作用:统一管理,减少类在包中 */public interface LoginContract {    interface  View extends BaseView{          String getUserName(EditText editText);          String getPassWorld(EditText editText);    }    interface  Model extends BaseModel{          void login(String userName,String passWorld,LoginListener listener);    }    abstract class   Presenter extends BasePresenter<View, Model>{        public  abstract  void login(Context context,String userName,String passWorld ,LoginListener listener);    }    interface  LoginListener{        void  loginSuccess();        void  loginFail();    }}

loginModel 具体实现类

/** * Created by Administrator on 2016/12/14. * 数据提供层 */public class LoginModel implements  LoginContract.Model{    private Handler mHandler=new Handler(Looper.getMainLooper());    @Override    public void login(final String userName,final  String passWorld, final  LoginContract.LoginListener listener) {        /**         * 模拟网路请求         */        new Thread(){            @Override            public void run() {                if(userName.equals("jack")&&passWorld.equals("123456")){                    System.out.println("登录成功");                }                try {                    Thread.sleep(1*1000);                    //回调到主线程中                    mHandler.post(new Runnable() {                        @Override                        public void run() {                            listener.loginSuccess();                        }                    });                } catch (InterruptedException e) {                    e.printStackTrace();                   mHandler.post(new Runnable() {                       @Override                       public void run() {                           listener.loginFail();                       }                   });                }            }        }.start();    }}

LoginPresenter

/** * Created by Administrator on 2016/12/14. * 业务逻辑控制层 */public class LoginPresenter extends LoginContract.Presenter {    @Override    public void login(Context context, String userName, String passWorld ,LoginContract.LoginListener loginListener) {        mView.RequstStart();        mModel.login(userName,passWorld,loginListener);    }}

LoginActivity

public class LoginActivity extends BaseActivity<LoginPresenter,LoginModel> implements LoginContract.View{    EditText mEtUserName;    EditText mEtPassWorld;    Button mBtnLogin;    private  AlertDialog.Builder  mBuilder;    private  AlertDialog mDialog;    @Override    public void init() {        mBuilder = new android.support.v7.app.AlertDialog.Builder(this);        mBuilder.setTitle("登录");        mBuilder.setMessage("正在登录 请稍等");    }    @Override    public void initView() {        mBtnLogin= (Button) this.findViewById(R.id.btn_login);        mEtUserName= (EditText) this.findViewById(R.id.et_userName);        mEtPassWorld= (EditText) this.findViewById(R.id.et_passWorld);    }    @Override    public void initData() {        mBtnLogin.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                String userName=getUserName(mEtUserName);                String  passWorld=getPassWorld(mEtPassWorld);                if (userName==null||userName.equals("")){                    Toast.makeText(mActivity,"用户名为空,请填写",Toast.LENGTH_SHORT).show();                    return;                }                if (passWorld==null||passWorld.equals("")){                    Toast.makeText(mActivity,"密码为空,请填写!",Toast.LENGTH_SHORT).show();                    return;                }                mPresenter.login(mActivity, userName, passWorld, new LoginContract.LoginListener() {                    @Override                    public void loginSuccess() {                        Toast.makeText(mActivity,"登录成功了",Toast.LENGTH_SHORT).show();                        ReqeustEnd();                    }                    @Override                    public void loginFail() {                        Toast.makeText(mActivity,"登录失败",Toast.LENGTH_SHORT).show();                        ReqeustEnd();                    }                });            }        });    }    @Override    public void RequstStart() {        mDialog= mBuilder.show();    }    @Override    public void ReqeustEnd() {        mDialog.dismiss();    }    @Override    public void onInternetError() {    }    @Override    public void ReqeustError() {    }    @Override    public int getContentView() {        return R.layout.activity_main;    }    @Override    public String getUserName(EditText editText) {        String userName=null;        if(editText!=null){            userName= editText.getText().toString().trim();        }        return userName;    }    @Override    public String getPassWorld(EditText editText) {        String  passWorld =null;        if(editText!=null){            passWorld= editText.getText().toString().trim();        }        return passWorld;    }}

CommUtils

public class CommUtils {    public static <T> T getT(Object o, int i) {        try {            return ((Class<T>) ((ParameterizedType) (o.getClass()                    .getGenericSuperclass())).getActualTypeArguments()[i])                    .newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ClassCastException e) {            e.printStackTrace();        }        return null;    }}

最后把布局文件代码贴下

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"    android:layout_width="match_parent" android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.jack.test.LoginActivity"><TextView    android:layout_width="match_parent"    android:text="用户名:"    android:layout_height="wrap_content" /> <EditText     android:id="@+id/et_userName"     android:layout_width="match_parent"     android:hint="请输入用户名"     android:layout_height="wrap_content" /> <TextView        android:layout_width="match_parent"        android:text="密 码:"        android:layout_height="wrap_content" /> <EditText        android:id="@+id/et_passWorld"        android:layout_width="match_parent"        android:hint="请输入你密码"        android:password="true"        android:inputType="textPassword"        android:layout_height="wrap_content" />    <Button        android:id="@+id/btn_login"        android:text="登录"        android:textSize="16sp"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

项目运行图
这里写图片描述

讲解的不多 相信大家看代码就会懂 如果还要什么错误或者很好的建议请留言

0 0