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

相关文章

Go 语言中Select与for结合使用break

func test(){i := 0for {select {case <-time.After(time.Second * time.Duration(2)):i++if i == 5{fmt.Println("break now")break }fmt.Println("inside the select: ")}fmt.Println("inside the for: ")}} 执行后

PMP–一、二、三模–分类–14.敏捷–技巧–原型MVP

文章目录 技巧一模14.敏捷--原型法--项目生命周期--迭代型生命周期,通过连续的原型或概念验证来改进产品或成果。每个新的原型都能带来新的干系人新的反馈和团队见解。题目中明确提到需要反馈,因此原型法比较好用。23、 [单选] 一个敏捷团队的任务是开发一款机器人。项目经理希望确保在机器人被实际建造之前,团队能够收到关于需求的早期反馈并相应地调整设计。项目经理应该使用以下哪一项来实现这个目标?

Jenkins--pipeline认识及与RF文件的结合应用

什么是pipeline? Pipeline,就是可运行在Jenkins上的工作流框架,将原本独立运行的单个或多个节点任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。 为什么要使用pipeline? 1.流程可视化显示 2.可自定义流程任务 3.所有步骤代码化实现 如何使用pipeline 首先需要安装pipeline插件: 流水线有声明式和脚本式的流水线语法 流水线结构介绍 Node:

结合Python与GUI实现比赛预测与游戏数据分析

在现代软件开发中,用户界面设计和数据处理紧密结合,以提升用户体验和功能性。本篇博客将基于Python代码和相关数据分析进行讨论,尤其是如何通过PyQt5等图形界面库实现交互式功能。同时,我们将探讨如何通过嵌入式预测模型为用户提供赛果预测服务。 本文的主要内容包括: 基于PyQt5的图形用户界面设计。结合数据进行比赛预测。文件处理和数据分析流程。 1. PyQt5 图形用户界面设计

第二十一章 rust与动静态库的结合使用

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust与动静态库的结合使用 目录 注意一、前言二、库生成三、库使用四、总结 一、前言 rust中多了很多类型的库,比如前面章节中我们提到基本的bin与lib这两种crate类型库。 如果你在命令行执行下列语句: rustc --help 那么你将能找到这样的内容: --crate-type [bin|li

前端---对MVC MVP MVVM的理解

就需要从前端这些年的从无到有、从有到优的变迁过程讲一下。 1. Web1.0时代 在web1.0时代并没有前端的概念,开发一个web应用多数采用ASP.NET/Java/PHP编写,项目通常用多个aspx/jsp/php文件构成,每个文件中同时包含了HTML、CSS、JavaScript、c#/Java/PHP代码,系统整体架构可能是这样子的: 我们可以看到服务端是比较重的,有一块既在客户

“设计模式双剑合璧:工厂模式与策略模式在支付系统中的完美结合”

工厂模式(Factory Pattern)和策略模式(Strategy Pattern)都是常见的设计模式,但它们解决的问题和应用场景不同。下面是它们的区别: 1. 目的不同: 工厂模式(Factory Pattern): 工厂模式的主要目的是创建对象。它通过定义一个创建对象的接口,让子类决定实例化哪一个具体类,从而将对象创建的逻辑与使用的代码分离。 工厂模式可以分为简单工厂、工厂方法和抽象

Windows电脑本地安装HFS文件共享服务结合内网穿透搭建低成本NAS

文章目录 前言1.软件下载安装1.1 设置HFS访客1.2 虚拟文件系统 2. 使用cpolar建立一条内网穿透数据隧道2.1 保留隧道2.2 隧道名称2.3 创建二级子域名访问本地hfs 总结 前言 本文主要介绍如何在Windows系统电脑使用HFS并结合cpolar内网穿透工具搭建低成本NAS,并实现使用公网地址远程访问管理本地局域网电脑存储的文件。 云存储作为一个新概念

Spring回顾之五 —— 测试,JUnit与SpringTest的完美结合

没有测试的程序,是不完整的,每一个从事写程序的人员,都应该坚持做单元测试,通过单元测试可以验证程序基本功能的有效性,从而保证整个系统的质量,功在一时,利在千秋。这里我们将尝试使用Junit和SpringTest,在之前的系统里添加测试功能。 第一步:JUnit与SpringTest的引入     JUnit故名知意,是一个专门为Java语言提供单元测试的框架。平时的开发过程中,单元

Windows系统使用小皮面板搭建Kodcloud结合内网穿透体验私有云盘

文章目录 1.前言2. Kodcloud网站搭建2.1. Kodcloud下载和安装2.2 Kodcloud网页测试 3. cpolar内网穿透的安装和注册4. 本地网页发布4.1 Cpolar云端设置4.2 Cpolar本地设置 5. 公网访问测试6.结语 1.前言 本文主要为大家介绍一款国人自研的在线Web文件管理器可道云,能够支持在线管理图片、播放音乐视频、编辑和查看文件