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

什么是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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值