美文网首页
Android中的依赖注入类型和选择

Android中的依赖注入类型和选择

作者: oh嘉嘉加加加 | 来源:发表于2020-03-31 13:53 被阅读0次

    Android中的依赖注入类型和选择

    优势:

    • Reusability of code
    • Ease of refactoring
    • Ease of testing

    什么是依赖注入

    举个不是依赖注入的例子

    class Car {
    
        private Engine engine = new Engine();
    
        public void start() {
            engine.start();
        }
    }
    
    
    class MyApp {
        public static void main(String[] args) {
            Car car = new Car();
            car.start();
        }
    }
    

    在这个例子中,Car 类构造了它自己的Engine,这将会有这些问题:

    • Car和Engine 紧密耦合,一个Car的实例只能使用一种Engine,没有子类或者可替代的实现可以被简单的使用。如果Car构建了自己的Engine,当你要使用Gas或者Electric 类型的Engines的时候你将创建两种类型的Car,而不是重用相同的Car,
    • 会使测试更加的困难

    什么样的代码看起来像是依赖注入呢?取代Car初始化的时候构建自己的Engine,以接收Engine对象作为一个参数的方式来代替。

    class Car {
    
        private final Engine engine;
    
        public Car(Engine engine) {
            this.engine = engine;
        }
    
        public void start() {
            engine.start();
        }
    }
    
    
    class MyApp {
        public static void main(String[] args) {
            Engine engine = new Engine();
            Car car = new Car(engine);
            car.start();
        }
    }
    

    在main方法中 先创建Engine实例然后作为参数来构造Car实例。这种基于依赖注入方法的好处是:

    • Car类可以重复利用,你可以传递不同实现的Engine给Car,比如说你可以定义一个你想让Car使用的Engine子类ElectricEngine,如果你使用依赖注入,你所需要做的仅仅是将上述代码中的Engine实例更新为ElectricEngine实例,Car的代码不需要做任何改动仍然可以运作。
    • Car类更容易进行测试

    Android中两种主要的依赖注入方式:

    • 构造器注入。这是上面code所描述的方式,你通过一个类的构造器给它传递依赖

    • 字段注入(或者Setter注入)。一些Android Framework 类比如说Activity类和Fragment类已经被系统实例化了,所以构造器注入是不可行的,通过字段注入,依赖项的实例化可以在这些类被创建后,代码如下。

    class Car {
    
        private Engine engine;
    
        public void setEngine(Engine engine) {
            this.engine = engine;
        }
    
        public void start() {
            engine.start();
        }
    }
    
    class MyApp {
        public static void main(String[] args) {
            Car car = new Car();
            car.setEngine(new Engine());
            car.start();
        }
    }
    

    自动依赖注入

    在上面的示例中,你自己创建,提供和管理了不同类的依赖关系,而不需要依赖库。这称之为手动依赖注入,

    Car的例子中只有一个依赖项,但是更多的依赖项和类用手动依赖注入将会变得冗长乏味。手动依赖注入也显示出了几个问题:

    • 对于大型App,获取所有依赖项并正确连接它们可能需要大量的样板代码。 在多层体系结构中,为了为顶层创建对象,您必须提供其下层的所有依赖关系。 举一个具体的例子,要制造一辆真正的汽车,您可能需要引擎,变速箱,底盘和其他零件。 发动机又需要气缸和火花塞。
    • 当您无法在传递依赖项之前构造依赖项时(例如,在使用延迟初始化或将对象作用域确定为应用程序流时),您需要编写并维护一个自定义容器(或依赖关系图),以管理您的生命周期 内存中的依赖项。

    有一些库通过自动化创建和提供依赖项的过程来解决这个问题。它们可分为两类:

    • 基于反射的解决方案,在运行时连接依赖项。
    • 静态解决方案,在编译时生成代码连接依赖项。

    Dagger 是一个流行的依赖注入库,可用于Java,Kotlin,Android,它由谷歌维护。Dagger通过创建和管理依赖关系图,让你在App中使用依赖注入提供了便利。它提供完全静态和编译时依赖关系,解决了基于反射解决方案(例如Guice)的许多开发和性能问题。

    依赖项注入的替代方法

    依赖项注入的替代方法是使用服务定位器。 服务定位器设计模式还改善了类与具体依赖关系的解耦。 您创建一个称为服务定位器的类,该类创建并存储依赖项,然后根据需要提供这些依赖项。

    class ServiceLocator {
    
        private static ServiceLocator instance = null;
    
        private ServiceLocator() {}
    
        public static ServiceLocator getInstance() {
            if (instance == null) {
                synchronized(ServiceLocator.class) {
                    instance = new ServiceLocator();
                }
            }
            return instance;
        }
    
        public Engine getEngine() {
            return new Engine();
        }
    }
    
    class Car {
    
        private Engine engine = ServiceLocator.getInstance().getEngine();
    
        public void start() {
            engine.start();
        }
    }
    
    class MyApp {
        public static void main(String[] args) {
            Car car = new Car();
            car.start();
        }
    }
    

    服务定位器模式与依赖项注入的不同之处在于元素的使用方式。 使用服务定位器模式,类可以控制并要求注入对象; 通过依赖注入,该应用程序可以控制并主动注入所需的对象。

    与依赖注入对比:

    • 服务定位器所需的依赖项集合使代码更难测试,因为所有测试都必须与相同的全局服务定位器进行交互。
    • 依赖项是在类实现中编码的,而不是在API表面中。因此,很难从外部了解一个类需要什么。因此,对Car或服务定位器中可用的依赖项的更改可能导致引用失败,从而导致运行时或测试失败。
    • 如果您希望将范围扩大到整个应用程序的生存期以外的任何地方,那么管理对象的生存期就比较困难。

    为您的应用选择正确的技术

    如上所述,这里有集中不同的技术去管理你的应用的依赖:

    • 手动依赖注入 仅适用于相对小的app,因为它的扩展性差,当项目变得庞大,传递对象会要求很多模板代码。
    • 服务定位器 从相对较少的样板代码开始,但是扩展性也很差。此外,测试变得更加困难,因为它们依赖于单例对象。
    • Dagger 为扩展而创建。它非常适合构建复杂的应用程序
    项目大小
    使用的工具 手动注入 服务定位器 Dagger Dagger Dagger

    如果你的小型app 似乎有可能增长,当没有太多代码需要修改时。你应该趁早考虑迁移到Dagger。

    总结

    依赖注入可以给你的app提供以下优势:

    • 类的可重用性和依赖解耦:换出依赖项的实现会更容易。 由于控制反转,因此代码重用得到了改善,并且类不再控制其依赖关系的创建方式,而是可以与任何配置一起使用。

    • 易于重构:依赖关系成为API表面的可验证部分,因此可以在对象创建时或在编译时对其进行检查,而不必将其隐藏为实现细节。

    • 易于测试:一个类部管理他自己的依赖,因此当你测试它的时候,你可以传给它不同实现的实现去测试你不同的的用例

    为了更好的立即依赖注入的好处,你应该在你的代码中手动尝试一下。

    资料来源

    https://developer.android.google.cn/training/dependency-injection?hl=zh_cn

    相关文章

      网友评论

          本文标题:Android中的依赖注入类型和选择

          本文链接:https://www.haomeiwen.com/subject/weewuhtx.html