Dagger2和MVP的结合

2023-11-23 11:38
文章标签 结合 mvp dagger2

本文主要是介绍Dagger2和MVP的结合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        先挖个坑,这里会有两篇整理后的dagger2和MVP的博客链接

        dagger2 入门   MVP示例

         Dagger2通过注解的方式,来实现对象的统一管理(简化初始化);

         MVP 主要是减少Activity/Fragment的代码量,只留下清晰的数据和界面的衔接(或者说数据填充);通过使用接口搭建关系,将耦合甩给抽象出来的接口,表现上就是界面逻辑、数据交接集中到了P层;数据的计算、处理是在M层;

         mvp有一个明显的好处:即便没有界面,也可通过“单纯的Java”将业务处理完毕,以等带界面衔接。这一点尤其适用于美工瞎几把改图不断完善设计的情况。

 

        在我没有将这两个东西结合起来使用的时候,我一直认为这是一件很复杂的事:

       1.      P层持有的V的句柄是从界面传过来的,而界面持有P的实例来调用触发方法,就这么来看,一个PV的逻辑就要提供两个Component…..好恐怖的感觉。

       2.      MVP已经比普通的类数量增加了2~3倍,再加上dagger2的接近两倍,我的天呐!

       3.      没试过,劳资的内心就是抵触,怎么滴吧!

       接下来直接来个例子吧,废话少说(因为废话都在前两篇说够了),以登录作为典型案例来处理。

       V:

/*** Created by ShuaiZhang on 2016/9/19.* 定义接口包括四个方法,分别是获取用户名;获取密码;* 显示登陆提示;显示登陆结果*/
public interface ILoginView {String getName();String getPwd();void showTip(String tip);void setResult(String result);
}
        M:
/*** Created by ShuaiZhang on 2016/9/19.* 我不想说话,你么也别打我*/
public class LoginBiz {//把用户名和密码连接成一个串假,假装是登录public String login(String name, String pwd){String result = "UserName:" + name +"\nPassword:" + pwd;return result;}
}
        P:

/*** Created by ShuaiZhang on 2016/9/19.* MVP,我还是啥也不想说*/
public class LoginPresenter {private ILoginView loginView;private LoginBiz loginBiz;public LoginPresenter(ILoginView loginView) {this.loginView = loginView;loginBiz = new LoginBiz();}public void doLogin(){loginView.showTip("Loading。。。");String result = loginBiz.login(loginView.getName(), loginView.getPwd());loginView.showTip("Success!");loginView.setResult(result);}
}

       为了增加篇幅,activity_login.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><EditTextandroid:id="@+id/edt_name"android:layout_width="match_parent"android:layout_height="wrap_content" /><EditTextandroid:id="@+id/edt_pwd"android:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/btn_login"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Login"/><TextViewandroid:id="@+id/txt_show"android:layout_marginTop="20dp"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>

       LoginActivity.class:

/*** Created by ShuaiZhang on 2016/9/19.* 登陆界面,实现登陆的抽象View ILoginView接口*/
public class LoginActivity extends AppCompatActivity implements ILoginView {LoginPresenter presenter;@BindView(R.id.edt_name)EditText edtName; // 用户名@BindView(R.id.edt_pwd)EditText edtPwd; // 密码@BindView(R.id.btn_login)Button btnLogin; //登录按钮@BindView(R.id.txt_show)TextView txtShow; //显示登录结果@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);ButterKnife.bind(this);presenter = new LoginPresenter(this);//初始化presenter//装X的拉姆达表达式btnLogin.setOnClickListener(v -> {if(checkInput()) presenter.doLogin();});}//输入检查private boolean checkInput(){if (edtName.getText().toString().equals("")){showTip("请输入姓名");return false;}if (edtPwd.getText().toString().equals("")){showTip("请输入密码");return false;}return true;}//传递用户名@Overridepublic String getName() {return edtName.getText().toString();}//传递密码@Overridepublic String getPwd() {return edtPwd.getText().toString();}//显示提示@Overridepublic void showTip(String tip) {Toast.makeText(this,tip,Toast.LENGTH_SHORT).show();}//显示结果@Overridepublic void setResult(String result) {txtShow.setText(result);}
}

        到这里,一个以Login为逻辑的MVP基本示例算是都有了。

        那么接下来,就是Dagger2了。

 

        想想前面三个疑问,握草,算了,还是慢慢写吧,先写个module试试?

/*** Created by ShuaiZhang on 2016/9/19.* 先写着试试*/
@Module //为登录提供点东西
public class LoginModule {//因为LoginPresenter构造器需要一个这玩意,所以放进了该Module的构造参数//这样,在LoginActivity初始化时就必然传递该参数private ILoginView loginView;//有参数的module构造器要求必须显式的传入本实体  必须携带参数public LoginModule(ILoginView loginView) {this.loginView = loginView;}@Provides //这个注解表名会被自动处理public LoginPresenter getLoginPresenter() {return new LoginPresenter(loginView);}
}

       Module有了,来个Component?

/*** Created by ShuaiZhang on 2016/9/19.* 这里决定怎么“组装”Component* 1.决定伴随生命周期(inject方法和参数),* 2.将会包含哪些实体(各module类中的@Provide返回类型)*/
@Component(modules=LoginModule.class)//这里还可以有一个依赖,我没搞懂,没添加
public interface LoginActivityComponent {void inject(LoginActivity activity);//有LoginActivity实现初始化,并绑定它的生命周期
}

       按照dagger2的套路下一步Build一下:

       注意:就是菜单栏的Build àRebuild Project;而Sync是没有用的,有时候这两个效果一样,但是这里不一样。

       接下来就是修改LoginActivity的代码了(只提供修改部分,因为其与的没差别):

@Inject
LoginPresenter presenter;
        为LoginPresenter添加@Inject注解,是它能自动获取dagger生成的对象。
//dagger不需要这里手动实现了
//presenter = new LoginPresenter(this);//初始化presenter
DaggerLoginActivityComponent.builder()//套路要求.loginModule(new LoginModule(this))//显式传入,LoginPresenter必要的参数ILoginView.build()//套路要求.inject(this);//绑定生命周期

       这里注释掉不在需要的presenter的初始化,然后添加DaggerLoginActivityComponent的初始化(名字好特么长)。

        Dagger2对MVP的影响只是在关系建立的"方式"上,事实上不对MVP的逻辑关系造成任何影响。它甚至不改变连接的结构,而是以一种新的衔接形式。

        一句话描述:dagger2为mvp提供了一种新的、统配的方式来建立相互的联系。


       没了,写完了,dagger2+mvp就这样搞定了,我擦,那我前面的顾虑呢?好吧,回头再看一下:

       问题:P层持有的V的句柄是从界面传过来的,而界面持有P的实例来调用触发方法,就这么来看,一个PV的逻辑就要提供两个Component…..好恐怖的感觉。

       其实这是个误解,Presenter的实例化只是需要一个参数,这个参数是作为presenter的一部分,也就是presenter不再需要独立的Component。之所以我会有这个疑问,其实还是我自己对MVP的理解没有更好的深入,这个….

       问题:MVP已经比普通的类数量增加了2~3倍,再加上dagger2的接近两倍,我的天呐!

       这个是逻辑分块,清晰化后的代价,换句话说:吃好的,就要多花钱;其实逻辑方面的简洁是优于代码量增加带来的不便的,如果你还在纠结代码量增加了,那么我只能说:兄弟,你代码量还不够,继续加油吧!

       问题:没试过,劳资的内心就是抵触,怎么滴吧!

       两个字:呵呵!

 

       你们以为到这就完了?图样森破!

       现在来看,LoginBiz类是不需要参数的,好像prenter里面那样写,没啥问题,也对;但是既然我们有了dagger,那么我们为什么不试着让它“更加dagger2”一些呢?

       修改presenter的构造方法:

public LoginPresenter(ILoginView loginView, LoginBiz loginBiz) {this.loginView = loginView;this.loginBiz = loginBiz;
}

       这个时候LoginModule也需要修改:

@Provides //这个注解表名会被自动处理
public LoginPresenter getLoginPresenter() {return new LoginPresenter(loginView,new LoginBiz());
}

        No!这不够dagger2!

        再改LoginModule:

@Provides //这个注解表名会被自动处理
public LoginPresenter getLoginPresenter(LoginBiz loginBiz) {return new LoginPresenter(loginView,loginBiz);
}
@Provides
public LoginBiz getLoginBiz(){return new LoginBiz();
}

        这里的getLoginPresenter的参数LoginBiz将会由下面的方法提供。


        那么,如何更加更加dagger2,接下来就自己开发吧,水平所限,我只能装逼到这了……

        提交的时候发现少个图,算了,哪天心情好哪天补上吧







这篇关于Dagger2和MVP的结合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/417666

相关文章

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

Python结合Flask框架构建一个简易的远程控制系统

《Python结合Flask框架构建一个简易的远程控制系统》这篇文章主要为大家详细介绍了如何使用Python与Flask框架构建一个简易的远程控制系统,能够远程执行操作命令(如关机、重启、锁屏等),还... 目录1.概述2.功能使用系统命令执行实时屏幕监控3. BUG修复过程1. Authorization

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

Python结合requests和Cheerio处理网页内容的操作步骤

《Python结合requests和Cheerio处理网页内容的操作步骤》Python因其简洁明了的语法和强大的库支持,成为了编写爬虫程序的首选语言之一,requests库是Python中用于发送HT... 目录一、前言二、环境搭建三、requests库的基本使用四、Cheerio库的基本使用五、结合req

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2