dagger 注入_探索Android中的依赖项注入-Dagger,Koin和Kodein

dagger 注入

Dagger has been the reigning dependency injection library in Android for a long time, but a few alternatives have appeared recently. I’ve used Dagger and Koin while working at Yelp and Hootsuite in enterprise-scale Android projects, and played around with Kodein in personal projects, and wanted to compare and contrast using the three different libraries.

Dagger长期以来一直是Android中统治性的依赖注入库,但是最近出现了一些替代方案。 在企业级Android项目的Yelp和Hootsuite工作时,我曾使用DaggerKoin ,在个人项目中与Kodein一起玩过 ,并且想使用这三个不同的库进行比较和对比。

There’s also a TL;DR section at the bottom of this article with a summary of the pros and cons of each library and links to more resources.

本文底部还有一个TL; DR部分,其中概述了每个库的优缺点,并提供了更多资源的链接。

前言:依赖注入与服务定位器 (Preamble: Dependency Injection vs Service Locator)

One thing to note is out of the three, technically only Dagger uses a dependency injection (DI) pattern; Koin and Kodein are service locators. In the service locator pattern, there’s a service locator class that creates and stores dependencies, then provides them on demand. Classes have control and ask for objects to be injected, whereas in dependency injection, the app has control and proactively injects the required objects into classes. Fundamentally, both patterns tackle the same problem: decoupling classes from concrete dependencies.

需要注意的三件事是,从技术上讲,只有Dagger使用了依赖注入(DI)模式。 Koin和Kodein是服务定位符。 在服务定位器模式中,有一个服务定位器类创建并存储依赖项,然后根据需要提供它们。 类具有控制权并要求注入对象,而在依赖项注入中,应用程序具有控制权并主动将所需的对象注入类。 从根本上讲,这两种模式都解决了相同的问题:将类与具体的依赖项分离。

一些示例代码 (Some sample code)

Let’s look at an example of injecting a Door object into House classes, then adding instances of the House classes to our main application. This isn’t meant to be a complete setup tutorial, since lots of those exist for all three libraries already, but I’ll provide some links to good existing ones.

让我们看一个将Door对象注入House类中,然后将House类的实例添加到我们的主应用程序中的示例。 这并不意味着要成为完整的设置教程,因为所有这三个库都已经存在了很多,但是我将提供一些指向现有现有库的链接。

Here’s our Door interface and the DoorImpl class that implements it:

这是我们的Door接口和实现它的DoorImpl类:

没有依赖注入 (Without dependency injection)

The House class:

房屋类:

class House {


    val door: Door = DoorImpl()
}

The MainApplication class:

MainApplication类:

class MainApplication : Application() {


    lateinit var house: House


    override fun onCreate() {
        super.onCreate()


        house = House()
        house.door.open()
    }
}

匕首 (Dagger)

The House class, with a Door provided via Dagger’s constructor injection:

House类,通过Dagger的构造函数注入提供了Door

class DaggerHouse @Inject constructor(val door: Door)

Then we need to create a module class to provide dependencies:

然后,我们需要创建一个模块类来提供依赖关系:

@Module
class DaggerModule {


    @Provides
    fun providesHouse(door: Door): DaggerHouse = DaggerHouse(door)


    @Provides
    fun providesDoor() : Door = DoorImpl()
}

And a component interface allowing the dependencies to be injected into the application:

还有一个组件接口,允许将依赖项注入到应用程序中:

@Component(modules = [DaggerModule::class])
interface DaggerComponent {


    fun house(): DaggerHouse


    fun door(): Door


    fun inject(mainApplication: MainApplication)
}

Finally, we can create the component and inject a Door in MainApplication’s onCreate():

最后,我们可以创建组件,并在MainApplicationonCreate()中插入一扇门

class MainApplication : Application() {


    @Inject
    lateinit var daggerHouse: DaggerHouse


    override fun onCreate() {
        super.onCreate()


        DaggerDaggerComponent.create().inject(this)
        daggerHouse.door.open()
    }
}

Dagger was the most complicated DI library and boilerplate-y to set up, but since it’s been around for so many years and is used widely, it was also the most easiest to troubleshoot by digging through existing answers on StackOverflow and Github issues.

Dagger是最复杂的DI库和建立的样板库,但是由于它已经存在了很多年并且被广泛使用,因此它也是最简单的解决问题的方法,方法是挖掘有关StackOverflow和Github问题的现有答案。

科恩 (Koin)

The House class, which can access Koin’s inject() method once it implements the KoinComponent interface:

House类,一旦实现KoinComponent接口,便可以访问Koin的inject()方法:

class KoinHouse : KoinComponent {


    val door by inject<Door>()
}

We have to declare a Koin module for providing the dependencies:

我们必须声明一个Koin模块来提供依赖项:

val koinModule = module {


    factory { KoinHouse() }


    factory { DoorImpl() as Door }
}

MainApplication has to implement the KoinComponent interface as well, and call startKoin() in its onCreate():

MainApplication还必须实现KoinComponent接口,并在其onCreate()中调用startKoin ()

class MainApplication : KoinComponent {


    val koinHouse by inject<KoinHouse>()


    override fun onCreate() {
        super.onCreate()


        startKoin {
            modules(koinModule)
        }
        koinHouse.door.open()
    }
}

科丁 (Kodein)

The House class needs to implement the KodeinAware interface, and also declare a value for kodein:

众议院类需要实现KodeinAware接口,并且还为kodein声明价值:

class KodeinHouse : KodeinAware {


    override val kodein = Kodein {
        import(kodeinModule)
    }


    val door by instance<Door>()
}

Again, we’ll need to declare a module for providing the dependencies:

同样,我们将需要声明一个用于提供依赖项的模块:

val kodeinModule = Kodein.Module(name = "kodeinModule") {


    bind<KodeinHouse>() with provider { KodeinHouse() }


    bind<Door>() with provider { DoorImpl() }
}

MainApplication has to implement the KodeinAware interface and declare a value for kodein:

MainApplication必须实现KodeinAware接口并声明kodein的值:

class MainApplication : Application(), KodeinAware {


    override val kodein = Kodein {
        import(kodeinModule)
    }


    val kodeinHouse by instance<KodeinHouse>()


    override fun onCreate() {
        super.onCreate()


        kodeinHouse.door.open()
    }
}

It feels boilerplate-y to have to override kodein in every KodeinAware class, although you can use the closestKodein() function inside an Android class or closestKodein(context) function in a non-Android one to retrieve your Kodein object.

尽管您可以在Android类中使用closestKodein()函数或在非Android类中使用closestKodein(context)函数来检索您的Kodein对象,但是必须在每个KodeinAware类中重写kodein还是样板的

他们背后的人 (The people behind them)

匕首 (Dagger)

Dagger 2, which is the version I’ll be covering in this article, is open-sourced by Google, so it’s actively maintained and backed by a big company. Dagger 1, which has been deprecated for a few years, was open-sourced by Square.

我将在本文中介绍的Dagger 2版本是Google开源的,因此它由一家大公司积极维护和支持。 已弃用了几年的Dagger 1由Square开源。

科恩 (Koin)

As far as I can tell, Koin is spearheaded by Arnaud Giuliani. So it’s an independent open-sourced project not backed by any specific companies. There’s an active community contributing to it.

据我所知,Koin是Arnaud Giuliani的带头人。 因此,这是一个不受任何特定公司支持的独立开源项目。 有一个活跃的社区对此做出了贡献。

科丁 (Kodein)

Kodein is also an independent open-source project with an active community of contributors, although the community is only roughly half the size as Koin’s (based on the number of stars, forks, and commits on Github).

Kodein也是一个独立的开源项目,拥有活跃的贡献者社区,尽管该社区的规模仅为Koin社区的一半(基于Github上的星星,分叉和提交的数量)。

他们如何工作 (How they work)

The three libraries have differing ways of implementing dependency injection. However, none of them use reflection, which was a major cause of crashes and performance issues with earlier libraries, such as Dagger 1 and Guice.

这三个库具有不同的实现依赖项注入的方式。 但是,它们都没有使用反射,这是早期库(例如Dagger 1和Guice)崩溃和性能问题的主要原因。

匕首 (Dagger)

It relies on annotation processing to generate a lot of boilerplate code at compile time. The generated code includes factories for all your classes, so that you can create instances of them without worrying about their dependencies.

它依靠注释处理在编译时生成大量样板代码。 生成的代码包括所有类的工厂,因此您可以创建它们的实例而不必担心它们的依赖性。

科恩 (Koin)

Koin uses Kotlin DSLs and lazily resolves your dependencies at runtime. It doesn’t do anything at compile time. It’s a much smaller and more lightweight library than Dagger, and doesn’t generate any code.

Koin使用Kotlin DSL并在运行时延迟解决您的依赖关系。 它在编译时不做任何事情。 它是一个比Dagger小得多,更轻量的库,并且不生成任何代码。

One neat feature is if your project uses Android Jetpack’s ViewModel component, Koin provides a few helper functions and keywords, such as the getViewModel() function, that lets you easily work with ViewModels out of the box.

一项精巧的功能是,如果您的项目使用Android Jetpack的ViewModel组件,Koin提供了一些帮助函数和关键字,例如getViewModel()函数,可让您轻松地使用ViewModels。

科丁 (Kodein)

Similar to Koin, it’s a small, lightweight library that lazily resolves dependencies at runtime. It also doesn’t generate any code, and makes extensive use of Kotlin inline functions under the hood as a performance optimization.

与Koin相似,它是一个小型轻量级的库,可在运行时延迟解决依赖关系。 它也不会生成任何代码,并在后台广泛使用Kotlin内联函数作为性能优化。

性能 (Performance)

There’s a Github project that compares the performance of several DI frameworks. The test dependencies are set up in a structure similar to the Fibonacci sequence, to simulate multiple levels of transitive dependencies. For example, the Fib8 class depends on a Fib7 object and a Fib6 object. So the number of injections required for FibN would equivalent to the time complexity of a recursive Fibonacci program, or O(1.618)ⁿ.

有一个Github项目 ,它比较了几个DI框架的性能。 测试依存关系的建立类似于斐波那契数列的结构,以模拟传递依存关系的多个级别。 例如, Fib8类依赖于Fib7对象和Fib6对象。 因此, FibN所需的进样次数将等于递归Fibonacci程序的时间复杂度,即O(1.618)ⁿ。

Here are the results of instantiating Fib12 on my Pixel 3 Android 10 device. This would be ~300 injections, so a small to medium sized Android project.

这是在我的Pixel 3 Android 10设备上实例化Fib12的结果。 这将是大约300次注入,因此是一个中小型的Android项目。

Image for post
Fib12 results
Fib12结果

And here are the results of instantiating Fib20. It requires ~15100 injections, so a fairly large Android project.

这是实例化Fib20的结果。 它需要大约15100次注入,因此是一个相当大的Android项目。

Image for post
Fib20 results
Fib20结果

The project’s README has results from several other devices as well.

该项目的自述文件也来自其他几种设备。

匕首 (Dagger)

Since Dagger does all its work at compile-time, it has the best runtime performance across all devices, at the cost of longer compile times.

由于Dagger在编译时完成所有工作,因此它在所有设备上都具有最佳的运行时性能,但代价是编译时间更长。

科恩 (Koin)

Koin is slower than Dagger, but the difference in setup and injection time isn’t really noticeable when using an app.

Koin比Dagger慢,但是在使用应用程序时,设置和注入时间的差异并不是很明显。

科丁 (Kodein)

Out of the three, Kodein has the slowest runtime performance. On some devices the measured times are about the same as Koin, but on others it’s significantly slower. When dependencies get complicated or the app is used on an older device, an injection can take over 20 milliseconds. The standard Android frame rate of 60 fps means the screen is refreshed every 16 ms; when an injection takes longer than that on the UI thread, the user may experience a janky screen.

在这三者中,Kodein的运行时性能最慢。 在某些设备上,测量时间与Koin大致相同,但在其他设备上,测量时间明显慢得多。 当依赖关系变得复杂或在较旧的设备上使用该应用程序时,注入可能会花费20毫秒以上的时间。 Android的标准帧率为60 fps,这意味着屏幕每16毫秒刷新一次; 当注入时间比UI线程的注入时间长时,用户可能会遇到屏幕混乱的情况。

测试中 (Testing)

匕首 (Dagger)

You can easily provide mocked versions of your classes by setting up a TestComponent to use in your tests. The TestComponent should extend the regular production component class. It can include production modules or mocked test modules.

通过设置要在测试中使用的TestComponent ,可以轻松提供类的模拟版本。 TestComponent应该扩展常规生产组件类。 它可以包括生产模块或模拟测试模块。

You can read more about it here.

您可以在此处了解更多信息。

科恩 (Koin)

Koin provides a lot of testing support as well. You can have your test class extend KoinTest to inject anything from your production Koin graph, as long as you call startKoin() before each test. You can also use KoinTestRule to create test modules that provide mocks instead.

Koin还提供了很多测试支持。 只要在每次测试之前调用startKoin() ,您就可以让您的测试类扩展KoinTest以注入生产Koin图中的任何内容。 您也可以使用KoinTestRule来创建提供模拟的测试模块。

Compared to Dagger, I find testing with Koin slightly more confusing to set up since there’s a bit more boilerplate required to get it working with mocks.

与Dagger相比,我发现用Koin进行的测试设置起来有些混乱,因为要使其与模拟一起工作还需要更多样板。

You can read more about it here.

您可以在此处了解更多信息。

科丁 (Kodein)

Similar to Dagger, you can create test Kodein modules that extend the production ones and override the bindings to provide mocks instead if necessary. The Kodein object in your test classes can use the test module instead.

与Dagger相似,您可以创建测试Kodein模块,以扩展生产模块,并在必要时覆盖绑定以提供模拟。 测试类中的Kodein对象可以改用测试模块。

Testing on Kodein seems relatively straightforward but unfortunately, there’s not much official documentation about it and I can’t tell how difficult it would be to use in larger, more complex projects. There’s a brief section about it here.

在Kodein上进行测试似乎相对简单,但不幸的是,有关Kodein的官方文档并不多,我无法确定在更大,更复杂的项目中使用它的难度。 有关于它的一个简短的部分在这里

调试经验 (Debugging Experience)

匕首 (Dagger)

Since all the work is done at compile-time, if you make a mistake in your code, you’ll know immediately because your project won’t build. However, compile-time error messages can be hard to understand. But since it’s so widely-used, you can usually find discussions and solutions on StackOverflow or Github from people who encountered similar problems.

由于所有工作都是在编译时完成的,因此,如果您在代码中犯了一个错误,您将立即知道,因为您的项目将无法生成。 但是,编译时错误消息可能很难理解。 但是,由于它的用途非常广泛,因此通常可以从遇到类似问题的人那里找到有关StackOverflow或Github的讨论和解决方案。

科恩 (Koin)

Since Koin lazily resolves dependencies at runtime, you wouldn’t know there’s a problem until you trigger the specific line of erroneous code and the app crashes. But once you run into the exception, you’ll be able to see a stacktrace and know exactly which line caused it. Koin’s exception error messages are pretty understandable and descriptive.

由于Koin会在运行时懒惰地解决依赖关系,因此只有在触发特定行的错误代码并且应用崩溃后,您才知道存在问题。 但是一旦遇到异常,您将能够看到堆栈跟踪并确切地知道是哪一行引起了该异常。 Koin的异常错误消息非常容易理解和描述。

It’s a newer library than Dagger, so it’s a bit harder to find answers on StackOverflow or similar websites.

它是一个比Dagger更新的库,因此在StackOverflow或类似网站上查找答案要困难一些。

科丁 (Kodein)

Similar to Koin, errors get caught during runtime and the exception error messages are quite helpful. However, it has even fewer users than Koin, so it’s difficult to find solutions online when you get stuck. I’ve had some luck asking in the #kodein channel in the Kotlin Slack; some of the most active Kodein contributors are in the channel and give detailed responses to people’s questions there.

与Koin相似,错误在运行时会被捕获,并且异常错误消息非常有帮助。 但是,它的用户数少于Koin,因此当您遇到困难时,很难在线找到解决方案。 我很幸运在Kotlin Slack的#kodein频道中提问; 该频道中有一些最活跃的Kodein贡献者,他们在那里对人们的问题进行了详细的回应。

语言 (Language)

匕首 (Dagger)

Dagger is written in and built for Java. For the most part, it works with Kotlin seamlessly, although there are a few Kotlin language features that don’t play well with it and you’ll have to watch out for. For example, if you want to provide an implementation of a @Provides method from an interface, you must explicitly specify the return type because Dagger relies on inspecting return types, even though Kotlin doesn’t require explicit return types.

Dagger是为Java编写并构建的。 在大多数情况下,它与Kotlin无缝兼容,尽管有一些Kotlin语言功能无法很好地与之配合使用,因此您必须提防。 例如,如果要从接口提供@Provides方法的实现,则必须显式指定返回类型,因为即使Kotlin不需要显式的返回类型,Dagger也要检查返回类型。

@Provides
// provides a Door
fun provideDoor(): Door = SlidingDoorImpl() 


@Provides
// provides a SlidingDoorImpl, not a plain Door!
fun provideDoor() = SlidingDoorImpl()

Dagger follows the JSR-330 specification. It’s a specification for dependency injection in Java that standardizes the annotations and interfaces that a Java DI library should support.

Dagger遵循JSR-330规范。 它是Java中依赖项注入的规范,用于规范Java DI库应支持的注释和接口。

科恩 (Koin)

As the name suggests, it’s written in and built for Kotlin, and using it looks very clean and idiomatic in Kotlin. You cannot use it in a pure Java project. However, if your project includes both Kotlin and legacy Java code, the latest version of Koin provides full Java interoperability out of the box (earlier versions required adding an additional koin-java dependency). However, there are a few extra things you’ll need to add to make it work and it won’t look as clean as it would in Kotlin. For example, lazy functions, which Koin uses extensively, are more verbose in Java, and you’ll have to add /@JvmField annotations to your modules.

顾名思义,它是为Kotlin编写和构建的,在Kotlin中使用它看起来非常干净和惯用。 您不能在纯Java项目中使用它。 但是,如果您的项目同时包含Kotlin和旧版Java代码,则最新版本的Koin可提供完整的Java互操作性(较早的版本需要添加额外的koin-java依赖项)。 但是,您还需要添加一些其他东西才能使其正常工作,并且看起来不像Kotlin那样干净。 例如,Koin广泛使用的惰性函数在Java中更为冗长,您必须在模块中添加/ @ JvmField批注。

科丁 (Kodein)

Kodein is also written in and built for Kotlin, and, like Koin, it looks clean and idiomatic in Kotlin code. You can’t use it in a pure Java project, but it would be fully interoperable with Java classes in a project with both Kotlin and Java, without requiring additional libraries.

Kodein也是为Kotlin编写的,并且是为Kotlin构建的,并且像Koin一样,在Kotlin代码中看起来很简洁。 您不能在纯Java项目中使用它,但是它将与具有Kotlin和Java的项目中的Java类完全互操作,而无需其他库。

Interestingly, it also supports JSR-330. Since Dagger and Guice are JSR-330 compliant as well, in theory it would be easier to refactor a Java class using Dagger or Guice to use Kodein instead. However, the documentation includes a warning that using JSR-330 annotations is much less performant than using classic Kodein injection methods, so unless you’re refactoring code that uses an existing DI library, it should be avoided.

有趣的是,它也支持JSR-330。 由于Dagger和Guice也符合JSR-330,因此从理论上讲,使用Dagger或Guice重构Java类以使用Kodein会更容易。 但是,文档中包含警告,与使用经典的Kodein注入方法相比,使用JSR-330批注的性能要低得多,因此,除非您要重构使用现有DI库的代码,否则应避免这样做。

关于在DI库之间迁移的注意事项 (Note on migrating between DI libraries)

Finally, I should point out that all three can peacefully coexist in the same project. If you’re thinking of migrating from one of the libraries to another, you can easily do it without much refactoring or work getting rid of the old library. You could leave all your code using your existing DI library untouched and just start writing new features using the new one. So don’t let a fear of refactoring stop you from experimenting with alternatives! The only gotcha to keep in mind is that adding a new library means some additional methods and classes.

最后,我要指出,这三个项目可以在同一项目中和平共处。 如果您正在考虑从一个库迁移到另一个库,则可以轻松进行此操作,而无需进行大量重构或摆脱旧库的工作。 您可以使用现有的DI库保留所有代码,而只是开始使用新的库编写新功能。 因此,不要担心重构会阻止您尝试替代方案! 要记住的唯一陷阱是添加新库意味着一些其他方法和类。

Here’s an example of a MainApplication class that contains a House object from Dagger, a Street object from Koin, and a Yard object from Kodein.

这是MainApplication类的示例,其中包含Dagger中的House对象,Koin中的Street对象和Kodein中的Yard对象。

class MainApplication : Application(), KoinComponent, KodeinAware {


    override val kodein = Kodein {
        import(kodeinModule)
    }


    @Inject
    lateinit var daggerHouse: DaggerHouse


    val koinStreet by inject<KoinStreet>()


    val kodeinYard by instance<KodeinYard>()


    override fun onCreate() {
        super.onCreate()


        DaggerDaggerComponent.create().inject(this)


        startKoin {
            modules(koinModule)
        }
    }
}

TL; DR (TL;DR)

My personal opinion would be to use Koin if you’re planning to write new features mostly in Kotlin, use Dagger if you’ll be writing them mostly in Java, and keep an eye on Kodein as another option for a mostly-Kotlin project as its features and community continue to grow.

我个人的观点是,如果您打算主要在Kotlin中编写新功能,请使用Koin;如果您打算主要在Java中编写新功能,请使用Dagger;并留意Kodein作为主要是Kotlin项目的另一种选择。它的功能和社区在不断增长。

匕首 (Dagger)

Here’s the official tutorial and a helpful introductory talk from Jake Wharton.

这是Jake Wharton官方教程和有用的入门演讲

Pros

优点

  • Actively maintained by Google

    由Google积极维护
  • Has been around the longest, so easy to find resources for learning and troubleshooting

    已有最长的时间,因此很容易找到学习和故障排除的资源
  • Errors are caught at compile-time

    在编译时捕获错误
  • Best runtime performance out of the three

    三种中最佳的运行时性能
  • Built for Java — nice if your project has a lot of Java code

    专为Java而建-如果您的项目中包含许多Java代码,那就太好了
  • Follows JSR-330 specifications

    遵循JSR-330规范

Cons

缺点

  • Steep learning curve; out of the three, most complicated to learn and understand

    陡峭的学习曲线; 三者中最难学和理解的
  • Requires the most boilerplate code when setting up

    设置时需要最多样板代码
  • Generates a lot of code

    生成大量代码
  • Slows down compile times

    减慢编译时间
  • Compilation errors can be hard to understand

    编译错误可能很难理解
  • Not built with Kotlin as its main use case; generally works with Kotlin but doesn’t play well with a few Kotlin language features

    并非以Kotlin为主要用例构建的; 通常可与Kotlin一起使用,但不能与Kotlin的一些语言功能配合使用

科恩 (Koin)

Here’s the official quickstart documentation and a great talk from Arnaud Giuliani. raywenderlich.com also has a helpful tutorial.

这是官方的快速入门文档,以及Arnaud Giuliani精彩演讲 。 raywenderlich.com也有一个有用的教程

Pros

优点

  • Shallower learning curve

    学习曲线较浅
  • Error messages in stacktraces are easy to understand

    堆栈跟踪中的错误消息很容易理解
  • Doesn’t slow down compile time or generate additional code

    不会减慢编译时间或生成其他代码
  • Built for Kotlin — clean and idiomatic syntax if your project has a lot of Kotlin

    专为Kotlin而建-如果您的项目中包含大量Kotlin,则语法简洁且惯用
  • Only DI library that provides additional support for Android Jetpack’s ViewModel — nice if you’re using an MVVM architecture that relies on the ViewModel component

    只有DI库为Android Jetpack的ViewModel提供了额外的支持—如果您使用的是依赖于ViewModel组件的MVVM体系结构,那很好

Cons

缺点

  • Smaller developer community than Dagger, so can be difficult to find answers and resources online (but the community is larger than Kodein’s and growing)

    与Dagger相比,开发者社区较小,因此可能很难在网上找到答案和资源(但是社区规模大于Kodein的社区,并且还在不断增长)
  • Since errors only appear at runtime, you won’t know you made a mistake until you test your app thoroughly and encounter a crash

    由于错误仅在运行时出现,因此您必须先彻底测试应用并遇到崩溃,才能知道自己犯了错误
  • Doesn’t look as clean in Java code

    在Java代码中看起来不干净
  • Doesn’t follow JSR-330 specifications

    不遵循JSR-330规范

科丁 (Kodein)

Here’s the official Android quickstart documentation and a helpful tutorial.

这是官方的Android快速入门文档有用的教程

Pros

优点

  • Shallower learning curve

    学习曲线较浅
  • Error messages in stacktraces are easy to understand

    堆栈跟踪中的错误消息很容易理解
  • Doesn’t slow down compile time or generate additional code

    不会减慢编译时间或生成其他代码
  • Built for Kotlin — clean and idiomatic syntax if your project has a lot of Kotlin code

    专为Kotlin而建-如果您的项目中包含大量Kotlin代码,则语法简洁明了
  • Follows JSR-330 specifications

    遵循JSR-330规范

Cons

缺点

  • Has the smallest developer community, so it can be hard to find resources when learning or troubleshooting. The community is growing though

    具有最小的开发人员社区,因此在学习或进行故障排除时可能很难找到资源。 社区在成长
  • Documentation is sometimes lacking or hard to navigate, especially with regards to testing

    有时缺少文档或很难浏览文档,尤其是在测试方面
  • Slowest runtime performance

    最慢的运行时性能
  • Doesn’t look as clean in Java code

    在Java代码中看起来不干净

其他DI选项 (Other DI options)

Finally, here are a few more Android DI libraries. They’re less widely used than the three I covered, but are actively maintained and would be fun to check out and experiment with.

最后,这里还有一些Android DI库。 它们没有我介绍过的三个广泛使用,但是它们得到了积极维护,可以很有趣地进行检查和试验。

Hope you found this exploration useful! I have a sample project on Github that sets up and uses all three DI libraries, where most of the code snippets in this article are from. If you have any thoughts or experiences about the three libraries you’d like to share, feel free to leave a comment :)

希望您发现此探索有用! 我在Github上有一个示例项目 ,该项目设置并使用了所有三个DI库,本文中的大多数代码段均来自此库。 如果您想分享三个库的想法或经验,请随时发表评论:)

翻译自: https://proandroiddev.com/exploring-dependency-injection-in-android-dagger-koin-and-kodein-e219a764be52

dagger 注入

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值