android_MVPd登录注册案例

    public class LoginPresenter {  
      
        private Login login;  
        private Context context;  
      
        // 提供初始化IView对象的一个方法  
      
        public LoginPresenter() {  
      
        }  
          
        public LoginPresenter(Login login,Context context) {  
            this.login = login;  
            this.context=context;  
        }  
      
        public boolean checkData(String phone,String pass) {  
            if(TextUtils.isEmpty(phone)||TextUtils.isEmpty(pass)){  
                Toast.makeText(context,"用户名或密码不能为空",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            //验证是否为手机号的正则表达式  
            String regex = "^1[3|4|5|7|8]\\d{9}";  
            if(!Pattern.matches(regex,phone)){  
                Toast.makeText(context,"手机号格式不正确",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            if(pass.length()<6){  
                Toast.makeText(context,"密码长度需要大于6位",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            return true;  
        }  
      
        public void login(String url,String username, String password) {  
            Map<String, String> map = new HashMap<>();  
            map.put("mobile", username);  
            map.put("password", password);  
            HttpUtils.getInstance().get(url, map,  
                    new Http() {  
                        @Override  
                        public void onSuccess(String data) {  
                            //解析  
                            Gson gson = new Gson();  
                            DataBean dataBean = gson.fromJson(data, DataBean.class);  
                            //获取code值,返回0为成功,1为失败  
                            if(dataBean.getCode().trim().equals("0")){  
                                login.succeed(data);  
                                Toast.makeText(context,dataBean.getMsg(),Toast.LENGTH_SHORT).show();  
                            }else{  
                                Toast.makeText(context,dataBean.getMsg(),Toast.LENGTH_SHORT).show();  
                            }  
                        }  
                        @Override  
                        public void onFiled(String message) {  
                            login.failed(message);  
                        }  
                    });  
        }  
      
        //防止内存泄漏  
        public void detatch(){  
            if (login != null) {  
                login = null;  
            }  
        }  
    }  

首先 MVP 是从经典的MVC架构演变而来

 系统C/S(Client/Server)三层架构模型:

  1)视图层(View):一般采用XML文件对应用的界面进行描述,使用的时候可以直接引入,极为方便,可以的大大缩短开发时间,也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了非常方便的通信实现。业务逻辑层(BLL):它的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计,也即是说它是与系统所应对的领域(Domain)逻辑有关,很多时候,也将业务逻辑层称为领域层。

  2)控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理。

  3)模型层(Model):对数据库的操作、以及其他和数据有关的的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。

三层结构架构三层间的交互及作用如下图所示:


MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。
在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过接口进行交互,从而使得在变更View时候可以保持Presenter的不变,可以多次复用。
在MVP里,应用程序的逻辑主要在Presenter来实现,其中的View是很薄的一层, 只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model。
MVP主要解决就是把逻辑层抽出来成P层,要是遇到需求逻辑上的更改就可以只需要修改P层了或者遇到逻辑上的大改我们可以直接重写一个P也可以,很多开发人员把所有的东西都写在了Activity/Fragment里面这样一来遇到频繁改需求或者逻辑越来越复杂的时候,Activity /Fragment里面就会出现过多的混杂逻辑导致出错,所以MVP模式对于APP来对控制逻辑和UI的解耦来说是一个不错的选择。


开始实例


一:布局

1:登录页面布局


    <?xml version="1.0" encoding="utf-8"?>  
    <RelativeLayout  
        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"  
        tools:context="activity.example.com.mvpframework.view.MainActivity">  
      
        <EditText  
            android:id="@+id/ed_phone"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:hint="请输入手机号"  
            android:layout_above="@+id/ed_pass"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true"  
            android:layout_marginBottom="55dp" />  
      
        <EditText  
            android:id="@+id/ed_pass"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:hint="请输入密码"  
            android:layout_above="@+id/btn_login"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true"  
            android:layout_marginBottom="94dp" />  
      
        <Button  
            android:id="@+id/btn_login"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="登录"  
            android:layout_marginLeft="65dp"  
            android:layout_marginStart="65dp"  
            android:layout_alignBaseline="@+id/btn_regis"  
            android:layout_alignBottom="@+id/btn_regis"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true" />  
      
        <Button  
            android:id="@+id/btn_regis"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="注册"  
            android:layout_alignParentBottom="true"  
            android:layout_alignParentRight="true"  
            android:layout_alignParentEnd="true"  
            android:layout_marginRight="43dp"  
            android:layout_marginEnd="43dp"  
            android:layout_marginBottom="130dp" />  
      
    </RelativeLayout>  

2:注册页面布局

    <?xml version="1.0" encoding="utf-8"?>  
    <RelativeLayout  
        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"  
        tools:context="activity.example.com.mvpframework.view.RegisActivity">  
      
        <EditText  
            android:id="@+id/ed_phone"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:hint="请输入手机号"  
            android:layout_alignParentTop="true"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true"  
            android:layout_marginTop="61dp" />  
      
        <EditText  
            android:id="@+id/ed_pass"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:hint="请输入密码"  
            android:layout_marginBottom="63dp"  
            android:layout_above="@+id/btn_regis"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true" />  
      
        <Button  
            android:id="@+id/btn_regis"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="注册"  
            android:layout_marginBottom="169dp"  
            android:layout_alignParentBottom="true"  
            android:layout_alignParentLeft="true"  
            android:layout_alignParentStart="true"  
            android:layout_marginLeft="130dp"  
            android:layout_marginStart="130dp" />  
      
    </RelativeLayout>  

3:登录成功跳转的页面,在此就不写了


二:定义了两个接口

1:登录、注册 成功或失败的接口

    public interface Login {  
        void succeed(String data);  
        void failed(String message);  
    }  

2:请求网络成功或失败的接口
    public interface Http {  
        void onSuccess(String data);  
        void onFiled(String message);  
    }  

三:M(model)层,提供数据,单例模式

    public class HttpUtils {  
        private static volatile HttpUtils instance;  
      
        private HttpUtils(){  
      
        }  
      
        public static HttpUtils getInstance(){  
            if(instance==null){  
                synchronized (HttpUtils.class){  
                    if(instance==null){  
                        instance = new HttpUtils();  
                    }  
                }  
            }  
            return instance;  
        }  
      
        public void get(String url, Map<String, String> map, final Http http) {  
            RequestParams params = new RequestParams(url);  
            for (Map.Entry<String, String> entry : map.entrySet()) {  
                params.addQueryStringParameter(entry.getKey(), entry.getValue());  
            }  
            x.http().get(params, new Callback.CommonCallback<String>() {  
                @Override  
                public void onSuccess(String result) {  
                    http.onSuccess(result);  
                }  
      
                @Override  
                public void onError(Throwable ex, boolean isOnCallback) {  
                    http.onFiled(ex.getMessage());  
                }  
      
                @Override  
                public void onCancelled(CancelledException cex) {  
      
                }  
      
                @Override  
                public void onFinished() {  
      
                }  
            });  
        }  
    }  




四:P(Presenter)层,逻辑处理

    public class LoginPresenter {  
      
        private Login login;  
        private Context context;  
      
        // 提供初始化IView对象的一个方法  
      
        public LoginPresenter() {  
      
        }  
          
        public LoginPresenter(Login login,Context context) {  
            this.login = login;  
            this.context=context;  
        }  
      
        public boolean checkData(String phone,String pass) {  
            if(TextUtils.isEmpty(phone)||TextUtils.isEmpty(pass)){  
                Toast.makeText(context,"用户名或密码不能为空",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            //验证是否为手机号的正则表达式  
            String regex = "^1[3|4|5|7|8]\\d{9}";  
            if(!Pattern.matches(regex,phone)){  
                Toast.makeText(context,"手机号格式不正确",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            if(pass.length()<6){  
                Toast.makeText(context,"密码长度需要大于6位",Toast.LENGTH_SHORT).show();  
                return false;  
            }  
            return true;  
        }  
      
        public void login(String url,String username, String password) {  
            Map<String, String> map = new HashMap<>();  
            map.put("mobile", username);  
            map.put("password", password);  
            HttpUtils.getInstance().get(url, map,  
                    new Http() {  
                        @Override  
                        public void onSuccess(String data) {  
                            //解析  
                            Gson gson = new Gson();  
                            DataBean dataBean = gson.fromJson(data, DataBean.class);  
                            //获取code值,返回0为成功,1为失败  
                            if(dataBean.getCode().trim().equals("0")){  
                                login.succeed(data);  
                                Toast.makeText(context,dataBean.getMsg(),Toast.LENGTH_SHORT).show();  
                            }else{  
                                Toast.makeText(context,dataBean.getMsg(),Toast.LENGTH_SHORT).show();  
                            }  
                        }  
                        @Override  
                        public void onFiled(String message) {  
                            login.failed(message);  
                        }  
                    });  
        }  
      
        //防止内存泄漏  
        public void detatch(){  
            if (login != null) {  
                login = null;  
            }  
        }  
    }  

五:V(View)层,展示页面,不做逻辑处理

1:MainActivity登录页面

    public class MainActivity extends AppCompatActivity implements Login,View.OnClickListener{  
      
        private EditText ed_phone;  
        private EditText ed_pass;  
        private Button btn_login;  
        private Button btn_regis;  
        private LoginPresenter presenter1;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            initView();  
        }  
      
        private void initView() {  
            //获取id  
            ed_phone = (EditText)findViewById(R.id.ed_phone);  
            ed_pass = (EditText)findViewById(R.id.ed_pass);  
            btn_login = (Button)findViewById(R.id.btn_login);  
            btn_regis = (Button)findViewById(R.id.btn_regis);  
            //点击监听  
            btn_login.setOnClickListener(this);  
            btn_regis.setOnClickListener(this);  
        }  
      
        @Override  
        public void onClick(View view) {  
            switch (view.getId()){  
                case R.id.btn_login:  
                    String user = ed_phone.getText().toString().trim();  
                    String pass = ed_pass.getText().toString().trim();  
                    //实例化p层  
                    presenter1 = new LoginPresenter(this,MainActivity.this);  
                    //效验输入的值是否符合格式  
                    boolean b = presenter1.checkData(user, pass);  
                    if(b){  
                        presenter1.login("http://120.27.23.105/user/login",user,pass);  
                    }  
                    break;  
      
                case R.id.btn_regis:  
                    //跳到注册页面  
                    startActivity(new Intent(MainActivity.this,RegisActivity.class));  
                    break;  
            }  
        }  
      
        @Override  
        public void succeed(String data) {  
                //登录成功跳到另一个页面  
                startActivity(new Intent(MainActivity.this,ShopActivity.class));  
        }  
      
        @Override  
        public void failed(String message) {  
            //正常情况不会执行,只有请求网络失败的时候才会执行,这里的失败是指网页打不开的失败  
            Toast.makeText(MainActivity.this,"网络异常,登录失败",Toast.LENGTH_SHORT).show();  
        }  
      
        //防止内存泄漏  
        @Override  
        protected void onDestroy() {  
            super.onDestroy();  
            if (presenter1 != null) {  
                presenter1.detatch();  
            }  
        }  
      
    }  


2:注册页面


    public class RegisActivity extends AppCompatActivity implements Login,View.OnClickListener{  
      
        private EditText ed_phone;  
        private EditText ed_pass;  
        private Button btn_regis;  
        private LoginPresenter presenter1;  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_regis);  
            ed_phone = (EditText)findViewById(R.id.ed_phone);  
            ed_pass = (EditText)findViewById(R.id.ed_pass);  
            btn_regis = (Button)findViewById(R.id.btn_regis);  
            btn_regis.setOnClickListener(this);  
        }  
      
        @Override  
        public void onClick(View view) {  
            String user = ed_phone.getText().toString().trim();  
            String pass = ed_pass.getText().toString().trim();  
            presenter1 = new LoginPresenter(this,RegisActivity.this);  
            boolean b = presenter1.checkData(user, pass);  
           if(b){  
                presenter1.login("http://120.27.23.105/user/reg",user,pass);  
            }  
        }  
      
        @Override  
        public void succeed(String data) {  
                finish();  
        }  
      
        @Override  
        public void failed(String message) {  
            //正常情况不会执行,只有请求网络失败的时候才会执行,这里的失败是指网页打不开的失败  
            Toast.makeText(RegisActivity.this,"网络异常,注册失败",Toast.LENGTH_SHORT).show();  
        }  
      
        //防止内存泄漏  
        @Override  
        protected void onDestroy() {  
            super.onDestroy();  
            if (presenter1 != null) {  
                presenter1.detatch();  
            }  
        }  
    }  


3:还有一个登录成功跳转的页面,在此就不写了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值