j2e*_*nue 46 dependency-injection dagger dagger-2
从匕首2 文档我注意到你可以有一个带@Singleton注释的类.标记类的目的是什么,@Singleton因为我试图在我的代码中执行此操作,但不生成单例对象.我不清楚用这个注释标记我的类的用途.
请从文档中关注以下声明:
注入类上的@Singleton注释也可用作文档.它提醒潜在的维护者,这个类可能被多个线程共享.*
@Singleton
class CoffeeMaker {
...
}
Run Code Online (Sandbox Code Playgroud)
更新:在查看froger_mcs答案后,我看到在Dagger 2中你可以通过模块或构造函数注入提供注射.因此,可以注入以下类,尽管不在模块中,
@Singleton
public class MyClass {
@Inject
public MyClass() {
}
}
Run Code Online (Sandbox Code Playgroud)
在这个版本中,构造函数是为我们注入的,在Android活动中,您只需执行以下操作即可获得:
@Inject
MyClass myClass;
//then in onCreate actually inject(this) from your graph of course.
Run Code Online (Sandbox Code Playgroud)
fro*_*mcs 49
@Singleton (以及任何其他范围注释)使您的类成为依赖关系图中的单个实例(这意味着只要Component对象存在,此实例将是"singleton").
简而言之 - 每次注入带@Singleton注释的类(带@Inject注释)时,只要从同一个组件中注入它,它就会是同一个实例.
有关更多信息,请参阅我的博客文章,了解@SingletonDagger 2中的注释和其他范围注释的工作原理:http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
Ari*_*eem 27
@Singleton没有真正创建一个单身人士,它只是一个Scope,建议不要使用,@Singleton因为它是误导,它给人的印象是我们实际上得到一个单身人士,但我们不是.
比方说,你注释你的数据库的依赖@Singleton,并链接了Component,现在让我们说,你这个初始化Component中Activities A和B,你将有你的数据库的不同实例在你的两个Activities这是大多数人不愿意.
你怎么克服这个?
初始化你Component曾经在你的Application类和其他地方,如静态访问Activities或者Fragments,现在这可能很快失控,如果你有超过20个Component's,因为你不能初始化所有的人都在你的Application班级,这样做也将放慢您的应用程序启动时间.
根据我的最佳解决方案是创建一个真实的Singleton,双重检查或其他变体,并静态使用它,getInstance()并@Provides在您的模块中使用它.
我知道它也伤了我的心,但请理解这@Singleton不是真的Singleton,它是一个Scope.
什么是单例?
android中的单例模式
在整个应用程序的整个生命周期中提供对自身的全局访问点的类的单个实例。
Dagger 中的 @Singleton 注释
对特定组件唯一的类的单个实例,它的访问仅限于组件的范围。
单例的目的
在依赖图(组件)中提供类的单个实例。一个组件通常在应用程序级别初始化,因为它在整个应用程序生命周期中只执行一个,并且所有活动和片段都可以访问。
让我们举个例子:
CoffeeComponent.kt
@Singleton
@Component
interface CoffeeComponent {
fun getCoffeeMaker():CoffeeMaker
fun inject(activityA: ActivityA)
fun inject(activityB: ActivityB)
}
Run Code Online (Sandbox Code Playgroud)
咖啡机.kt
@Singleton
class CoffeeMaker @Inject constructor()
Run Code Online (Sandbox Code Playgroud)
咖啡应用程序.kt
class CoffeeApplication : Application() {
private val component by lazy {
DaggerCoffeeComponent.builder().build()
}
fun getAppComponent(): CoffeeComponent = component
}
Run Code Online (Sandbox Code Playgroud)
推荐做法
始终对组件进行延迟初始化。
场景:假设您的团队决定添加一个入门/教程屏幕或合并一些其他设计,这些设计在初始屏幕期间不需要该组件,这将有助于最大程度地减少启动延迟。永远记住,组件初始化是昂贵的。
活动A.kt
import dagger.Lazy
class ActivityA: AppCompatActivity() {
@Inject
lateinit var coffeeMaker1:Lazy<CoffeeMaker>
@Inject
lateinit var coffeeMaker2:Lazy<CoffeeMaker>
private val component by lazy {
(application as CoffeeApplication).getAppComponent()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_activityB.setOnClickListener { startActivity(Intent(this, NewActivity::class.java)) }
component.inject(this)
println("Activity A CoffeeMaker 1 - ${coffeeMaker1.get()}")
println("Activity A CoffeeMaker 2 - ${coffeeMaker2.get()}")
}
}
Run Code Online (Sandbox Code Playgroud)
如果你的类构建成本很高,请使用 dagger 的 Lazy 初始化,请不要将它与 kotlin 的 Lazy 混淆。你必须导入
import dagger.Lazy
@Inject
lateinit var coffeeMaker1:Lazy<CoffeeMaker>
Run Code Online (Sandbox Code Playgroud)
活动B.kt
class ActivityB: AppCompatActivity() {
@Inject
lateinit var coffeeMaker1:Lazy<CoffeeMaker>
@Inject
lateinit var coffeeMaker2:Lazy<CoffeeMaker>
private val component by lazy {
(application as CoffeeApplication).getAppComponent() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new)
component.inject(this)
println("Activity B CoffeeMaker 1 - ${coffeeMaker1.get()}")
println("Activity B CoffeeMaker 2 - ${coffeeMaker2.get()}")
}
}
Run Code Online (Sandbox Code Playgroud)
您将获得日志输出为
注意:
If you want to share a singleton instance between activities, lazily initialize them in the application level, if you initialize them in an activity you will end up with different instance as the components are different
| 归档时间: |
|
| 查看次数: |
33571 次 |
| 最近记录: |