在不同的活动中使用 AppComponent.Inject() (Dagger2)
Use AppComponent.Inject() in different activities (Dagger2)
我有两个使用 ViewModelProvider 的活动,必须用 Dagger 注入。
要在 activity 中提供注入,我必须调用 appComponent.inject() 方法。我可以进入 MainActivity。但是我不能在其他活动中使用它(显然是因为 appComponent.inject() 将 MainActivity 实例作为参数)。
所以,问题是:
我应该如何处理 AppComponent(或 smth.else),以便能够从不同的活动(不仅从 MainActivity)获取 AppComponent 的实例。
P.S。可能是关于 Dagger Scopes 的问题,但我不知道该怎么做。
AppComponent.kt
...
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun create(): AppComponent
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
@Inject
lateinit var viewModelProvider: Provider<MainActivityViewModel.Factory>
private val viewModel: MainActivityViewModel by viewModels { viewModelProvider.get() }
private lateinit var recyclerView : RecyclerView
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
RecyclerViewAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appComponent.inject(this)
setContentView(R.layout.activity_main)
setupViewModel()
setupUI()
}
private fun setupViewModel(){
viewModelProvider.get()
viewModel.setQuery("Apple")
}
private fun setupUI(){
recyclerView = findViewById(R.id.recyclerView)
GridLayoutManager(this,3, RecyclerView.VERTICAL,false
).apply {
recyclerView.layoutManager = this
}
recyclerView.adapter = adapter
addRepeatingJob(Lifecycle.State.STARTED) {
viewModel.images.collectLatest(adapter::submitData)
}
}
}
ViewPager.kt
class ViewPagerActivity : AppCompatActivity() {
@Inject
lateinit var viewModelProvider: Provider<MainActivityViewModel.Factory>
private val viewModel: MainActivityViewModel by viewModels { viewModelProvider.get() }
private lateinit var viewPager: ViewPager2
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
ViewPagerAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_pager)
Log.d("dbg", intent.getIntExtra("ARG", 0).toString())
setupViewModel()
setupUI();
}
private fun setupUI()
{
viewPager = findViewById(R.id.viewPager)
viewPager.adapter = adapter
addRepeatingJob(Lifecycle.State.STARTED) {
viewModel.images.collectLatest(adapter::submitData)
}
}
private fun setupViewModel()
{
viewModelProvider.get()
}
}
谢谢。
AppComponent 的 Builder 接受一个 Application。您尚未指定如何创建或存储 AppComponent,但大概是在 Application 实例中或静态字段中以保留其 @Singleton
属性.
在这种情况下,您可以创建第二个 inject
方法,名称相似或不同,它采用您的 SecondActivity
:
fun inject(mainActivity: MainActivity)
fun inject(secondActivity: SecondActivity)
其中每个都是一个 成员注入方法:Dagger 将在编译时检查对象,找出标有 @Inject
注释的内容,然后调用方法并在调用 inject
时填充字段。您可以为此使用相同的组件或使用不同的组件。
最终,如果您希望能够在 Activity 中注入相同的实例,但在不同的 Activity 之间注入不同的实例,您可以查看第二个组件(可能是子组件),其范围注释如 @ActivityScope
你会写。您还可以考虑采用 Hilt,它会为您管理其中的一些范围。
我有两个使用 ViewModelProvider 的活动,必须用 Dagger 注入。
要在 activity 中提供注入,我必须调用 appComponent.inject() 方法。我可以进入 MainActivity。但是我不能在其他活动中使用它(显然是因为 appComponent.inject() 将 MainActivity 实例作为参数)。
所以,问题是: 我应该如何处理 AppComponent(或 smth.else),以便能够从不同的活动(不仅从 MainActivity)获取 AppComponent 的实例。
P.S。可能是关于 Dagger Scopes 的问题,但我不知道该怎么做。
AppComponent.kt
...
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun create(): AppComponent
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
@Inject
lateinit var viewModelProvider: Provider<MainActivityViewModel.Factory>
private val viewModel: MainActivityViewModel by viewModels { viewModelProvider.get() }
private lateinit var recyclerView : RecyclerView
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
RecyclerViewAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appComponent.inject(this)
setContentView(R.layout.activity_main)
setupViewModel()
setupUI()
}
private fun setupViewModel(){
viewModelProvider.get()
viewModel.setQuery("Apple")
}
private fun setupUI(){
recyclerView = findViewById(R.id.recyclerView)
GridLayoutManager(this,3, RecyclerView.VERTICAL,false
).apply {
recyclerView.layoutManager = this
}
recyclerView.adapter = adapter
addRepeatingJob(Lifecycle.State.STARTED) {
viewModel.images.collectLatest(adapter::submitData)
}
}
}
ViewPager.kt
class ViewPagerActivity : AppCompatActivity() {
@Inject
lateinit var viewModelProvider: Provider<MainActivityViewModel.Factory>
private val viewModel: MainActivityViewModel by viewModels { viewModelProvider.get() }
private lateinit var viewPager: ViewPager2
private val adapter by lazy(LazyThreadSafetyMode.NONE) {
ViewPagerAdapter(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_pager)
Log.d("dbg", intent.getIntExtra("ARG", 0).toString())
setupViewModel()
setupUI();
}
private fun setupUI()
{
viewPager = findViewById(R.id.viewPager)
viewPager.adapter = adapter
addRepeatingJob(Lifecycle.State.STARTED) {
viewModel.images.collectLatest(adapter::submitData)
}
}
private fun setupViewModel()
{
viewModelProvider.get()
}
}
谢谢。
AppComponent 的 Builder 接受一个 Application。您尚未指定如何创建或存储 AppComponent,但大概是在 Application 实例中或静态字段中以保留其 @Singleton
属性.
在这种情况下,您可以创建第二个 inject
方法,名称相似或不同,它采用您的 SecondActivity
:
fun inject(mainActivity: MainActivity)
fun inject(secondActivity: SecondActivity)
其中每个都是一个 成员注入方法:Dagger 将在编译时检查对象,找出标有 @Inject
注释的内容,然后调用方法并在调用 inject
时填充字段。您可以为此使用相同的组件或使用不同的组件。
最终,如果您希望能够在 Activity 中注入相同的实例,但在不同的 Activity 之间注入不同的实例,您可以查看第二个组件(可能是子组件),其范围注释如 @ActivityScope
你会写。您还可以考虑采用 Hilt,它会为您管理其中的一些范围。