当前位置: 首页 > 科技观察

Android注解的三大框架Dagger、Hilt、Koin有什么区别?

时间:2023-03-20 17:02:23 科技观察

Dagger和Koin无疑是Android中最流行的两个依赖注入框架。这两个库服务于相同的目的并且看起来非常相似,但它们在底层的工作方式却截然不同。那么希尔特是什么?Hilt是一个内部使用Dagger的库,只是简化了它的使用,所以我这里说的Dagger也适用于Hilt。在本文中,我不会告诉您应该选择哪个库。相反,我想向您展示它们的根本区别以及这些差异如何影响您的应用程序。Dagger如果我们想让Dagger提供某个类的实例,我们所要做的就是在构造函数中添加@Inject注解。添加这个注解后,Dagger会在构建时为这个类生成一个Factory。在这种情况下,由于它的类名为CompositeAdapter,因此它会生成一个名为CompositeAdapter**_**Factory的类。此类包含创建CompositeAdapter类实例所需的所有信息。如您所见,工厂类实现了get()并返回了一个新的CompositeAdapter实例。这其实就是该类实现的Provider接口中指定的方法。其他类可以使用Provider接口来获取类的实例。如果我们用Hilt替换Dagger会怎么样?在这个例子中,没有区别。Hilt是一个在内部使用Dagger的库,我向您展示的类是由Dagger生成的。如果您使用Hilt,它确实会为我们生成一些额外的类,这些类可以简化Dagger的使用并减少我们需要编写的样板代码量。但核心保持不变。KoinKoin使用与Dagger和Hilt完全不同的方法来管理依赖项。要在Koin中注册依赖项,我们不会使用任何注释,因为Koin不会生成任何代码。相反,我们必须为模块提供工厂,这些模块将用于创建项目中所需的每个类的实例。Koin将对这些工厂类的引用添加到InstancesRegistry类中,该类包含对我们编写的所有工厂的引用。此映射中的键是类的全名或使用命名参数时提供的名称。对应的值就是我们写的工厂,会用来创建类的实例。要获得依赖项,我们需要调用get()(例如在工厂类中)或通过在活动或片段中的委托属性上调用inject()来延迟加载get()。get()方法将查找为给定类型的类注册的工厂并将其注入其中。效果如何?Dagger生成代码以提供依赖项,而Koin则不会,这实际上有一些含义。1.错误处理由于Dagger是一个编译时依赖注入框架,如果我们忘记提供某些依赖项,我们几乎会立即知道我们的错误,因为我们的项目将无法构建。例如,如果我们忘记将@Inject注释添加到构造函数的CompositeAdapter并尝试将其注入到片段中,构建将失败并显示一个适当的错误,告诉我们到底出了什么问题。Koin中的情况有所不同,因为它不生成任何代码。如果我们忘记为CompositeAdapter类添加工厂,应用程序将成功构建,但每当我们请求此类的实例时都会抛出RuntimeException。它可能会在应用程序启动时发生,因此我们可能会立即注意到它,但它也可能稍后在其他屏幕上或用户执行某些特定操作时发生。2.对构建时间的影响Koin不生成任何代码的优势在于它对我们构建时间的影响要小得多。Dagger需要一个注释处理器来扫描代码并生成适当的类。这可能需要一些时间,并且可能会减慢我们的构建速度。3.对运行时性能的影响另一方面,Koin由于在运行时解决依赖关系,因此其运行时性能略差。差别有多大?为了估计性能差异,我们可以使用这个库,其中RafaVázquez测量并比较了不同设备上的两个库。测试数据的编写方式模拟了多层次的传递依赖性,因此它不仅仅是一个具有4个类的虚拟应用程序。如您所见,Dagger对启动性能几乎没有影响。另一方面,在Koin中,我们可以看到它需要花费很多时间。依赖注入在Dagger中也比在Koin中稍快。总结正如我在本文开头所说,我在这里的目标不是告诉您使用哪个库。我在两个不同的大项目中使用过Koin和Dagger。老实说,我认为你选择Dagger还是Koin并不重要,重要的是它允许你编写干净、简单且可单元测试的代码。我认为所有的图书馆:Koin、Dagger和Hilt都服务于这个目的。所有这些库都有它们的长处,我希望了解它们在幕后如何工作将帮助您自己决定哪个库最适合您的应用程序。