Android MVP框架学习笔记,demo模拟一个注册登录过程

最近学习MVVM想到之前看过的MVP框架,虽然已经过时了,但是还是觉得有可以借鉴的地方,所以又拿出来复习了一下,用一个小小的demo来练练手。
模拟一个注册登录过程,首先理一下代码逻辑:
1、注册登录的过程当中,P需要做什么?
V向P发起请求,P向M请求数据,M发起网络请求并在请求完成后通过接口将数据回调给P,P持有V的引用,完成数据请求玩的操作。
2、M需要做什么?
M负责发起网络请求以及数据的处理
3、V需要做什么?
V初始化P,并通过P来通知M发起网络请求

在这里插入图片描述
首先新建如上几个文件,具体作用如下
IPresenter中定义所需的功能 注册、登录、获取用户信息

public interface IPrestener {
    void login();

    void register();

    void getUserInfo();
}

IView中定义网络请求后view需要执行的操作

public interface IView<T> {
    void onNetStart();

    void onSuccess(T result);

    void onFail(String msg);
}

IModel内暂时不需要什么内容,主要为了在presenter中初始化的统一

IRegisterView继承IView,注册需要获取view中的用户名、密码,并且注册完成后需要将用户信息返给view所以IRegisterView中定义如下内容

public interface IRegisterView extends IView {
    String getUserName();

    String getPassword();

    void userInfo(User user);
}

ILoginView继承IView,登录需要获取view中的用户名密码

public interface ILoginView extends IView {
    String getUserName();
    String getPassword();
}

MainPresenter考虑作为全局的presenter,可以在里面实现所有的presenter功能,实现IPresenter接口,所有方法在IPresenter中定义,在MainPresenter中实现

public class MainPresenter implements IPrestener {
    private IView view;
    private IModel model;

    public MainPresenter(IView view) {
        this.view = view;
    }

    @Override
    public void login() {
        model = new LoginModel();
        String userName = ((ILoginView) view).getUserName();
        String passWord = ((ILoginView) view).getPassword();
        ((LoginModel) model).getLoginResult(userName, passWord, new NetCallBack() {
            @Override
            public void onStart() {
                view.onNetStart();
            }

            @Override
            public void onSuccess(Object result) {
                view.onSuccess(result);
            }

            @Override
            public void onFail(String msg) {
                view.onFail(msg);
            }
        });
    }

    @Override
    public void register() {
        model = new RegisterModel();
        String userName = ((IRegisterView) view).getUserName();
        String passWord = ((IRegisterView) view).getPassword();
        ((RegisterModel) model).userRegister(userName, passWord, new NetCallBack() {
            @Override
            public void onStart() {
                view.onNetStart();
            }

            @Override
            public void onSuccess(Object result) {
                view.onSuccess(result);
            }

            @Override
            public void onFail(String msg) {
                view.onFail(msg);
            }
        });
    }

    @Override
    public void getUserInfo() {
        model = new RegisterModel();
        ((RegisterModel) model).getUserInfo(new NetCallBack() {
            @Override
            public void onStart() {
                view.onNetStart();
            }

            @Override
            public void onSuccess(Object result) {
                ((IRegisterView) view).userInfo((User) result);
            }

            @Override
            public void onFail(String msg) {
                view.onFail(msg);
            }
        });
    }

}

这里可以看到MainPresenter构造函数需要传入view,并且MainPresenter始终持有view的引用。定义统一的成员变量IModel,在不同的方法中分别进行初始化。

RegisterModel、LoginModel中模拟注册以及返回用户信息的操作,模拟网络请求

public class RegisterModel implements IModel {
    public void userRegister(final String username, final String password, final NetCallBack callBack) {
        if (username == null || "".equals(username)) {
            callBack.onFail("请输入用户名");
            return;
        }
        if (password == null || "".equals(password)) {
            callBack.onFail("请输入密码");
            return;
        }
        callBack.onStart();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                LoginModel.USER = username;
                LoginModel.PASS = password;
                callBack.onSuccess("注册成功");
            }
        }, 3000);

    }

    public void getUserInfo(final NetCallBack callBack) {
        callBack.onStart();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                callBack.onSuccess(new User("zyq", 25, "男"));
            }
        },3000);
    }
}
public class LoginModel implements IModel {
    public static String USER = "";
    public static String PASS = "";

    public void getLoginResult(final String s1, final String s2, final NetCallBack callBack) {
        if (s1 == null || "".equals(s1)) {
            callBack.onFail("请输入用户名");
            return;
        }
        if (s2 == null || "".equals(s2)) {
            callBack.onFail("请输入密码");
            return;
        }
        callBack.onStart();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (USER.equals(s1) && PASS.equals(s2)) {
                    callBack.onSuccess("登陆成功");
                } else {
                    callBack.onFail("请输入正确的用户名、密码");
                }
            }
        }, 3000);

    }
}

NetCallBack是一个Model回调给Presenter网络请求结果的接口,此处在具体项目中建议使用retrofit观察者代替。

public interface NetCallBack<T> {
    void onStart();

    void onSuccess(T result);

    void onFail(String msg);
}

User是一个用户信息实体类

public class User {
    private String username;
    private int age;
    private String sex;

    public User(String username, int age, String sex) {
        this.username = username;
        this.age = age;
        this.sex = sex;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

下面是两个activity中的代码

public class MainActivity extends AppCompatActivity implements ILoginView {
    private ActivityMvpMainLayoutBinding binding;
    private MainPresenter presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_mvp_main_layout);
        presenter = new MainPresenter(this);
    }

    @Override
    public String getUserName() {
        return binding.etUsername.getText().toString().trim();
    }

    @Override
    public String getPassword() {
        return binding.etPassword.getText().toString().trim();
    }

    @Override
    public void onNetStart() {
        Toast.makeText(getApplicationContext(), "开始登陆", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onSuccess(Object result) {
        Toast.makeText(getApplicationContext(), (String)result, Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onFail(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }

    public void loginClick(View view) {
        presenter.login();
    }
}
public class RegisterActivity extends AppCompatActivity implements IRegisterView {
    private ProgressDialog dialog;
    private ActivityRegisterLayoutBinding binding;
    private MainPresenter presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_register_layout);
        presenter = new MainPresenter(this);
        dialog = new ProgressDialog(this);
    }

    @Override
    public String getUserName() {
        return binding.etUsername.getText().toString().trim();
    }

    @Override
    public String getPassword() {
        return binding.etPassword.getText().toString().trim();
    }

    @Override
    public void userInfo(User user) {
        StringBuffer sb = new StringBuffer();
        sb.append("用户:");
        sb.append(user.getUsername());
        sb.append("\n");
        sb.append("年龄:");
        sb.append(user.getAge());
        sb.append("\n");
        sb.append("性别:");
        sb.append(user.getSex());
        dialog.dismiss();
        showToast(sb.toString());
        startActivity(new Intent(RegisterActivity.this, MainActivity.class));
    }

    @Override
    public void onNetStart() {
        showToast("开始请求");
        dialog.show();
    }

    @Override
    public void onSuccess(Object result) {
        dialog.dismiss();
        showToast((String) result);
        presenter.getUserInfo();
    }

    @Override
    public void onFail(String msg) {
        dialog.dismiss();
        showToast(msg);
    }

    public void register(View view) {
        presenter.register();
    }

    private void showToast(final String str) {
        new Handler(getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
            }
        });
    }

}

现在来理一下整体的调用流程(以注册获取用户信息为例)
1、activity中实例化MainPresenter并将自己传给MainPresenter的构造函数,此时MainPresenter持有RegisterActivity的实例。
2、点击注册按钮调用presenter的register方法,register方法中实例化RegisterModel,并调用RegisterModel中的userRegister。
3、userRegister中模拟网络请求,模拟的网络请求结果回调给MainPresenter传入RegisterModel的接口。
4、收到RegisterModel回调后,通过持有的RegisterActivity通知activity进行相关操作。
5、在activity的onSuccess中调用presenter的获取用户信息方法
·
·
·
获取完用户信息后开始登录流程,登录流程和注册流程一样

总结:View、Model通过Presenter进行联系,View调用Presenter->Presenter调用Model->Model获取完数据回调给Presenter->Presenter通过持有的View的引用将数据交给View进行UI操作。MVP的好处是UI只负责显示,数据的获取和处理都交给Model去实现,并且View和Model不进行直接联系,降低了代码的耦合度。开始可能会觉得代码写起来复杂,可是在大型项目中可以大大降低耦合度,方便后期维护,并且代码逻辑看起来简洁明了,不会造成一个activity上千行的代码。

第一次做学习笔记,有错误或者有可以改进的地方,还望指出 蟹蟹

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值