您的位置:首页 > 运维架构 > 网站架构

Android 进阶之 MVP 架构

2021-01-22 23:29 736 查看

写在前边

小伙伴们,两天不见了,很想念你们哦!这两天一直没来得及更新,因为最近在研究 Android 的 MVP 架构,我觉得这也是一个重要的 Android 进阶的技术点。

昨天我还问我身边的小伙伴,我问他 “你知道我们学的 Android 有哪些架构吗?” 他一脸懵逼的告诉我 “你还别说,Android 的架构我还真不知道。” 他也不算是小白了,学了 Android 也有一年了,正是当年和我一起从安卓基础学到现在的一个小伙伴。然后我通过这几天的架构学习简单和他讲了一下,他当时恍然大悟。

这就说明一个情况,你不去主动去学习了解这些与 Android 相关技术点,总会被慢慢淘汰的。我的这个小伙伴估计是淘汰不了了,哈哈,他身边有我指点着呢!

我充分利用这两天的空余时间,通过查看文档和博客的学习,彻底的理解了 MVP 架构的结构。然后把手头的项目用 MVP 架构做了一遍,也算是入坑了。

从公众号一开始关注我的读者知道,我不会为了发文章而写文章的,如果手头真没有值得分享的技术文章,我是不会随便写一篇来应付过去的。从我个人的写作经验可以得出,一篇真正有价值,让别人能够学习到真正有营养的技术的一篇文章从起草到构思,再到总结整理,最后排版直到成功分享到公众号至少需要两个多小时甚至还不够。曾经我也做过实验,把一篇技术文用一个小时迅速完成,读者的收获往往没有,阅读量惨淡,读者的脑子里对这个技术点只是一个大体的框架。读者如果真想借助文章的肩膀往上爬,这还对写文章的作者有很严格的要求的。虽然现在做公众号的人多了,但是,像张哥说的一样,高质量的文章还是屈指可数的。一味地坚持每天发文,你是否考虑到文章的质量呢?废话不多说,直接上 MVP 架构,今天说啥也让你弄懂。


正文

介绍 MVP 架构之前,现在简单了解一下MVC 架构,M『 Model 模型层』V『 View 视图层』C『 Control 控制层』。MVC 架构是一个很适合初学者入门的架构,做 Servlet 后台服务用的比较多,现在公司基本用 ssm 框架做开发了。MVC 这里不多深入介绍,想要了解,网上很多文档供参考学习。在 Android中 MVC 架构其实不常用,也不适合用。因为 View 视图层和 Control 控制层的代码都在整个 Activity 中实现的,不能清晰的展现出 View 层和 Control 控制层的所要处理的功能的分离。所以我们 Android 进一步对 MVC 进行改进,就演化成了现在常用到的 MVP 架构 M『 Model 模型层』V『 View 视图层』P『 Presenter 层』Presenter 用英语翻译过来就是代表者的意思。他在 MVP 架构中起到什么作用呢?它的作用就是连接 View 层和 Model 层的的桥梁。说白了就是,他是一根电话线,保持两端的通信。MVP 和 MVC 的另一个区别就是,Model 层和 View 视图层不能直接通信,而是通过这个 Presenter 这根线的连接才能通信。之前的 MVC 呢?就不能把 Control 控制层看做成电话线了,而是看做成处理逻辑的一个类,View 层和 Control 层还有 Model 层两两互相可以通信,三者之间的数据传输可以很随意没有限制。回过头来再看 MVP 架构,Model 层和 View 层的数据都会传到 Presenter 层做两者的处理。写到这里不懂不要紧,下面会具体说明。

我们再来看一组示意图:

MVC 结构示意图:

MVP 结构示意图

是不是对这两个架构的区分又清晰了一步?

有小伙伴要着急了,兄弟别废话了,直接上代码吧,别来讲这些概念了。上边这些概念是让你脑子里形成一个大体的框架,对 MVP 架构有一个基本的认识,才会对下边要举的例子有个清晰的认识。

用 MVP 架构写一个用户登录的例子吧!

第一步 : 包的目录分布

总目录 :


分目录 :

第二步 : Model层

User 类属于 bean,为数据类:

1public class User {
2    private String username ;
3    private String password ;
4    public String getUsername() {
5        return username;
6    }
7    public void setUsername(String username) {
8        this.username = username;
9    }
10    public String getPassword() {
11        return password;
12    }
13    public void setPassword(String password) {
14        this.password = password;
15    }
16}

IOnLoginListener 为「判断登录是否成功」的接口:

1public interface IOnLoginListener {
2    //登录成功
3    void loginSuccess(User user);
4    //登录失败
5    void loginFailed();
6}

IUserImp 为登录功能的接口:

1public interface IUserImp {
2    //登录
3    public void login(String username, String password, IOnLoginListener loginListener);
4}

UserImp 为 IUserImp 接口的实现类:

1public class UserImp implements IUserImp {
2    @Override
3    public void login(final String username, final String password, final IOnLoginListener loginListener) {
4        //模拟子线程耗时操作
5        new Thread() {
6            @Override
7            public void run() {
8                try {
9                    Thread.sleep(2000);
10                } catch (InterruptedException e) {
11                    e.printStackTrace();
12                }
13                //模拟登录成功
14                if ("zhy".equals(username) && "123".equals(password)) {
15                    User user = new User();
16                    user.setUsername(username);
17                    user.setPassword(password);
18                    loginListener.loginSuccess(user);
19                } else {
20                    loginListener.loginFailed();
21                }
22            }
23        }.start();
24    }
25}

第三步 : View视图层

View 中的 IUserLoginView 为实现与 UI 交互的的方法接口:

1public interface IUserLoginView {
2    //View获取用户名和密码
3    String getUserName();
4    String getPassword();
5    //清除用户名和密码
6    void clearUserName();
7    void clearPassword();
8    //耗时提示ProgressBar
9    void showLoading();
10    void hideLoading();
11    //提醒 登录成功失败
12    void toMainActivity(User user);
13    void showFailedError();
14}

第四步 : Presenter 层

Persenter 类中的作用来连接 View 层和 Model 层的:

1public class UserLoginPresenter {
2    private IUserImp userBiz;
3    private IUserLoginView userLoginView;
4    private Handler mHandler = new Handler();
5    public UserLoginPresenter(IUserLoginView userLoginView) {
6        this.userLoginView = userLoginView;
7        this.userBiz = new UserImp();
8    }
9    public void login() {
10        userLoginView.showLoading();
11        userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new IOnLoginListener() {
12            @Override
13            public void loginSuccess(final User user) {
14                //需要在UI线程执行
15                mHandler.post(new Runnable() {
16                    @Override
17                    public void run() {
18                        userLoginView.toMainActivity(user);
19                        userLoginView.hideLoading();
20                    }
21                });
22            }
23            @Override
24            public void loginFailed() {
25                //需要在UI线程执行
26                mHandler.post(new Runnable() {
27                    @Override
28                    public void run() {
29                        userLoginView.showFailedError();
30                        userLoginView.hideLoading();
31                    }
32                });
33            }
34        });
35    }
36    public void clear() {
37        userLoginView.clearUserName();
38        userLoginView.clearPassword();
39    }
40}

第五步 : LoginActivity 去实现登录功能

1public class UserLoginActivity extends Activity implements IUserLoginView{
2    private EditText mEtUsername,mEtPassword;
3    private Button mBtnClear,mBtnLogin;
4    private ProgressBar mPbLoading;
5    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
6    @Override
7    protected void onCreate(@Nullable Bundle savedInstanceState) {
8        super.onCreate(savedInstanceState);
9        setContentView(R.layout.activity_main);
10        initViews();
11    }
12    private void initViews()
13    {
14        mEtUsername = (EditText) findViewById(R.id.id_et_username);
15        mEtPassword = (EditText) findViewById(R.id.id_et_password);
16        mBtnClear = (Button) findViewById(R.id.id_btn_clear);
17        mBtnLogin = (Button) findViewById(R.id.id_btn_login);
18        mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
19        //登录
20        mBtnLogin.setOnClickListener(new View.OnClickListener() {
21            @Override
22            public void onClick(View v) {
23                mUserLoginPresenter.login();
24            }
25        });
26        //取消登录
27        mBtnClear.setOnClickListener(new View.OnClickListener() {
28            @Override
29            public void onClick(View v) {
30                mUserLoginPresenter.clear();
31            }
32        });
33    }
34    @Override
35    public String getUserName() {
36        return mEtUsername.getText().toString();
37    }
38    @Override
39    public String getPassword() {
40        return mEtPassword.getText().toString();
41    }
42    @Override
43    public void clearUserName() {
44        mEtUsername.setText("");
45    }
46    @Override
47    public void clearPassword() {
48        mEtPassword.setText("");
49    }
50    @Override
51    public void showLoading() {
52        mPbLoading.setVisibility(View.GONE);
53    }
54    @Override
55    public void hideLoading() {
56        mPbLoading.setVisibility(View.VISIBLE);
57    }
58    @Override
59    public void toMainActivity(User user) {
60        Toast.makeText(this, user.getUsername() +
61                " login success , to MainActivity", Toast.LENGTH_SHORT).show();
62    }
63    @Override
64    public void showFailedError() {
65        Toast.makeText(this,
66                "login failed", Toast.LENGTH_SHORT).show();
67    }
68}

当初我学习这个架构的时候有点懵逼,各种你接口各种实现类,弄得我晕头转向的。我就一直看一直琢磨,相信最后总会看会的,这些努力和付出最终让我彻底明白了这个叫 MVP 的架构。我给大家提供一个好的方法,通过断点调试,一步步跟着程序运行,这样就很容易明白的知道整个架构的逻辑和流程。

我们通过上边的一系列学习,有的小伙伴就要问了,怎么一个简单的登录系统怎么代码量变多了?没错,代码量是变多了,你有没有感觉到项目逻辑架构清晰了很多?而且每个架构层中的每个类都要执行的规定好的任务『 View 视图层主要管与 UI 界面做交互的(如:监听用户按钮事件);Model 模型层主要是管理数据对象的;Presenter 层主要管理 Model 和 View 的数据通信处理逻辑运算的』。这种架构做小项目是体现不出有优点的,等以后到了公司开发大型的项目,代码量成千上万,MVP 架构的优势就很明了的展现出来,而且包括后期的项目维护,这种优势相比把代码写到一个 Activity 里边要好的多。比如公司的项目要加一个功能,按照往常的做法,先把整个 Activity 里边的逻辑理清,当你理清逻辑,估计公司的黄花菜都凉凉了。然而用 MVP 架构呢,你可以准确的找到实现该功能的接口,随意的添加该方法到里边,找到实现该方法的实现类然后实现该功能就 ok 了。只有你真正的去做了,才能体会到这种架构的好处,只听我在这说 bb 没什么软用的。

好了,这两天我就主要了解了 MVP 架构,有什么不足可在后台留言我后期会补充。

后记

为了今天能够给大家更新干货,这些大部分都是在上午上课的时候总结的。做一篇干货文章真的不容易,这篇文章从开始写到发布到公众号你还被不信,我算了算加起来前后用了三个半小时来更新这篇文章。公众号高质量的文章也越来越少,都是为了利益毫不顾忌的更新低质量的文章。利益互推、瞎转发几乎成了一种常态,我希望我的公众号一直能这样高质量的输出干货,通过自己理解总结整合分析反思推敲琢磨,努力打造一个独一无二纯净的公众号。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: