首页 > 其他分享 >Android Dagger2简单使用

Android Dagger2简单使用

时间:2023-12-08 19:07:00浏览次数:30  
标签:testA dagger class TestA TestB Dagger2 简单 Android public

Dagger是一个很古老的框架了,当初诞生时候,主要是为了模块之间的解耦。本篇文章主要介绍一下如何使用dagger2,后续会介绍其原理。

AS集成

对于现在的AS项目,一般都是会集成Kotlin和Java混写,所以可以在想要使用dagger的模块module的gradle下加入如下配置。

implementation 'com.google.dagger:dagger:2.21'
kapt 'com.google.dagger:dagger-compiler:2.21'

注意这里用到了kapt,这就要求我们对应module的gradle顶部有如下配置:

apply plugin: 'kotlin-kapt'

如何使用

 假设我们现在存在一个类TestA, 结构如下:

public class TestA {

        private int count = 0;
        
        public String getValue() {
            return "123321";
        }
        
        public int addSelf(){
            return ++count;
        }
    }

我们现在呢,要在TestB中使用到TestA的对象实例,常规写法呢,就是new一个对象进行方法调用:

  • 常规写法
public class TestB {

        private final TestA testA = new TestA();

        public void show() {
            for (int i = 0; i < 2; i++) {
                testA.addSelf();
                System.out.println(testA.getValue());
            }
        }
    }
  • 使用dagger

常规写法要求我们对于一个对象必须要实例化,才能使用。那么在项目比较大型的时候,如果很多地方都用到了该对象,且进行了实例化。那么后续只要对象构造器里增加一个入参,那么就需要修改所有地方。

这样很容易出错,dagger这个时候就可以起作用了,dagger可以帮我们自动去书写实例化对象的代码,而我们只需要关注使用testA对象即可。

让我们看下使用dagger,这里代码怎么写。

public class TestB {

        @Inject
        TestA testA;

        public void show() {
            for (int i = 0; i < 2; i++) {
                testA.addSelf();
                System.out.println(testA.getValue());
            }
        }
    }

可以看到,区别就是将new TestA去掉了,加上了@Inject注解,让Dagger自动帮我们去进行TestA的实例化,我们只需要加上注解后,在下方直接使用其方法即可。

现在我们知道了dagger的作用和简单的使用场景,我们来看下如果要实现上述例子中TestA这种直接加注解来实例对象的方式,该怎么操作。

使用dagger来实现TestA自动实例化

下图是Dagger里最基本的几个注解的使用及关系。

Android Dagger2简单使用_ide

对于上述TestA的例子。我们首先按照上图所示,定义一个Module,如下:

@Module
    public class TestAModule {

        @Provides
        public TestA provide() {
            return new TestA();
        }
    }

这里对于provide方法可以任意命名,只要返回值是TestA就可以。同时TestAModule也可以任意命名,只要加上Module注解即可。

 接着,我们定义桥梁Component,类和方法也可以随意命名。

@Component(modules = TestAModule.class)
    public interface TestAComponent {

        void injectIntoTestB(TestB testB);
    }

注意Component上要写上,该Component所对应的Module,以便Dagger可以关联两者。同时内部定义一个接口也需要传入TestB对象,以便告诉Dagger,我们想要在哪个类中使用TestA实例。

做完这些,最后一步就是在TestB中使用了。

public class TestB {

        @Inject
        TestA testA;

        public void show() {
            for (int i = 0; i < 2; i++) {
                testA.addSelf();
                System.out.println(testA.getValue());
            }
        }
    }

注意这里TestA不可以是private修饰。

我们需要先build一下,编译完成后,还需要最后一步,在TestB中运行一下Dagger。可以在show方法中加上如下方法:

DaggerTestAComponent.create().injectIntoTestB(this);

DaggerTestAComponent是Dagger在我们构建编译时候为我们生成的,所以此时不编译是看不到这个类的,必须编译一下。

运行一下,我们就可以使用这个类了。所有Dagger自动生成的类都是以Dagger开头。

如果找不到文件!!\color{red}{如果找不到文件!!}如果找不到文件!!

可能某些小伙伴发现,编译后仍然找不到这个类,那么说明你的项目开启了增量编译,需要gradle.properties中将其关闭。     在 gradle.properties 中加上如下配置,然后删除build文件夹,重新编译。

kapt.incremental.apt = false

最后我们运行一下,发现日志可以成功打印,说明执行成功了。

注意这个时候,TestB文件中张这样。

public class TestB {

    @Inject
    TestA testA;

    public void show() {
        DaggerTestAComponent.create().injectIntoTestB(this);
        for (int i = 0; i < 2; i++) {
            testA.addSelf();
            System.out.println(testA.getValue());
        }
    }

实现单例

上述我们简单实现了个例子,同时我们可以在类中直接实例化一个对象并进行使用。我们看下如何实现。

我们可以在Provides注解标注的方法上加上Singleton注解,表示通过该方法生成的对象为单例对象,但是要注意,该单例的范围仅限于inject时候传入的对象。

比如:

@Module
public class TestAModule {

    @Provides
    @Singleton
    public TestA provide() {
        return new TestA();
    }
}

注意在Component上也要加上Singleton注解。

@Component(modules = TestAModule.class)
@Singleton
public interface TestAComponent {

    void injectIntoTestB(TestB testB);

    void injectIntoTestC(TestC testC);
}

对于上述方法,我在TestB和TestC中使用时候:

public class TestB {

    @Inject
    TestA testA1;

    @Inject
    TestA testA2;

    public void show() {
        DaggerTestAComponent.create().injectIntoTestB(this);
        System.out.println(testA1);
        System.out.println(testA2);
    }
}

public class TestC {

    @Inject
    TestA testA1;
    
    @Inject
    TestA testA2;

    public void dd() {
        DaggerTestAComponent.create().injectIntoTestC(this);
        System.out.println("C:" + testA1);
        System.out.println("C:" + testA2);
    }
}

我们同时运行dd和show方法时候,会发现两个dd方法内地址打印一样,show方法内地址打印一样,但是dd方法和show方法打印的地址就不一样了。这是因为单例的范围和inject传入的对象有关,只在传入的对象范围内生效。

name标签

Dagger存在一个Name标签,主要用于确定对象的不同生成方式。比如我们TestA存在多个构造器。

public class TestA {

    public TestA() {
    }

    public TestA(int count) {
        this.count = count;
    }

    private int count = 0;

    public String getValue() {
        return "123321 " + count;
    }

那么可以在module中使用name来区分不同方式来生成对象实例。

@Module
public class TestAModule {
    @Provides
    @Named("11")
    public TestA provide() {
        return new TestA();
    }

    @Provides
    @Named("22")
    public TestA provide2() {
        return new TestA(22);
    }

我们在TestB中使用,

public class TestB {

    @Inject
    @Named("11")
    TestA testA1;

    @Inject
    @Named("22")
    TestA testA2;

    public void show() {
        DaggerTestAComponent.create().injectIntoTestB(this);
        System.out.println("11=>" + testA1.getValue());
        System.out.println("22=>" + testA2.getValue());
    }

运行一下方法 show,可以看到此时testA1和testA2分别调用了不同的构造器生成了对象。

总结

个人感觉,dagger在当下直接使用,比较鸡肋,想不到很合适的使用场景,毕竟当下这么多框架和新技术,对于各种场景,完全有更合适的框架。所以本文只打算对dagger研究这么多。为后续Hilt学习打个基础吧。

标签:testA,dagger,class,TestA,TestB,Dagger2,简单,Android,public
From: https://blog.51cto.com/u_16175630/8741120

相关文章

  • android adb查看分区 adb查看手机分区大小
    androidadb查看分区adb查看手机分区大小_棉花糖的技术博客_51CTO博客https://blog.51cto.com/u_12218/8714703 System分区:就是我们刷ROM的分区Data分区:分区就是我们装APK的分区Cache分区:是缓存分区SDCard分区:就是挂载的SD卡概念:概念描述根目录......
  • Misc_XCTF_WriteUp | [简单] 凯撒大帝在培根里藏了什么
    题目提示:究极简单题(认真格式为flag{你所得到的大写字符串}题目:分析根据提示,该题用到凯撒密码和移位密码。题目中字符串非A即B,先用培根密码的方式解密:之后不断更换偏移量对培根密码解密的结果进行凯撒密码解密。当偏移量为6时得到的字符串可读:按格式提交flag......
  • mumu模拟器frida-server-14.2.18-android执行报错{"type":"error","description":&
    前言全局说明环境:物理机Windos11mumu模拟器下载:MuMuInstaller_3.1.5.0_nochannel-mumu12_zh-Hans_1687258372mumu模拟器:MuMuNG-setup-V3.6.4.2333-1110175123.exemumu模拟器官网:https://mumu.163.commumu模拟器官网-历史版本:https://mumu.163.com/update/一、问题c......
  • C++socket服务器与客户端简单通信流程
    服务器和客户端简单通信的流程,做一个简单的复习:1.服务器创建的流程代码如下,各个重要函数已经写注释:#include<iostream>//推荐加上宏定义#defineWIN32_LEAN_AND_MEAN#include<winsock2.h>#include<Windows.h>#pragmacomment(lib,"ws2_32")usingnamespacestd;i......
  • AI爆文写作变现:简单几步创建一个GPTs:公众号情感故事大师
    昨天已经详细介绍了GPTs的创建步骤,今天就再给大家写一个关于公众号情感故事大师的GPTs需要的可以参考昨天的文章:AI爆文写作变现:GPTs实现精细化高质量文章创作-美食类先看效果:这是我用这个GPTs写的文章发布的效果:创建公众号情感故事大师GPTBuilder:Hi!I'llhelpyoubuild......
  • does not have a SELinux domain defined. android 开机启动
    问题:dmesg [  46.089306]init:Servicemysvc2 doesnothaveaSELinuxdomaindefined. servicemysvc1/system/vendor/bin/app1classmainuserrootgrouprootsystemreadprocdisabledwritepid/dev/cpuset/foreground/tasksservicemysvc2......
  • 开发APP应用程序到底是选ios好还是Android好?
    哈喽大家好,我是咕噜老尼,现在我们都知道,APP应用已经覆盖了我们的生活,成为我们生活中不可缺少的一部分,手机系统主要分两种,分别是安卓和ios系统,不少APP开发公司在制作手机APP时,都需要将同一款APP做成两种,分别适应安卓和iOS系统。那么,开发APP应用程序到底是选ios好还是Android好,我们一......
  • RK3399 ANDROID 8.1 取消USB权限弹窗,直接默认给权限
    RK3399ANDROID8.1取消USB权限弹窗,直接默认给权限由于前段时间公司的平板接了一个USB设备,但是每次要弹框请求USB权限,客户反映很不好。所以就在系统层,把权限默认给了。系统是8.1的,其他系统思路应该也是一样的。思路是,在弹框的一瞬间,自动给权限。就是先找到弹框的代码,在弹框......
  • C++/CLI 包装引用 Native C++ 简单测试
    托管C++这个项目名:CppCLI。Animals.h#pragmaonceusingnamespaceSystem;namespaceZoological{publicrefclassAnimals{public:intGetLegs();voidSetLegs(intlegs);String^GetName();voidSetName(String^nam......
  • python--元组、列表、集合、字典、函数简单总结与区分
    元组:用“()”,不可修改其中的元素,有索引,tuple可建立一个元组。列表:用“【】”,可修改其中元素,有索引,可用list函数创建。集合:用“{}”,且{}相当于set()相当于set(【】),无序,无索引,可修改其中元素。字典:用”{}“,无索引,可修改其中元素,成对出现(区别于集合)。    例如:mynumber={"a":1,"b"......