如何获取已使用应用程序上下文初始化的组件

huangapple go评论81阅读模式
英文:

How to get Component already initialized with Application context

问题

我刚刚开始使用dagger2,尽管我已经阅读并查阅了文档以获取主要思想,但我不明白注入应用程序上下文的适当方式是什么。

我知道有类似的问题,比如这个或者这个,但这些使用了AndroidInjector,让我更加困惑。我想要理解的是,一旦ContextComponent被初始化并且是一个Singleton,我如何获取ContextComponent的实例(其中包含Application的上下文),以便调用ContextComponent.getSharedPreferenceSpecific()并获得一个使用Application上下文初始化的SharedPreferenceManagerSpecific的实例?

以下是我创建的类,SharedPreferenceManagerSpecific只是为了理解如何向类中注入上下文。

当执行活动的代码时,我得到以下错误:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.amgdeveloper.articleReader/com.amgdeveloper.articleReader.ui.MainActivity}: java.lang.IllegalStateException: com.amgdeveloper.articleReader.dagger.ContextModule must be set
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)

ContextModule.kt

@Module
class ContextModule(private val app: Application) {

    @Provides
    @Singleton
    fun provideContext(): Context = app

}

ContextComponent.kt

@Singleton
@Component(modules = [ContextModule::class])
interface ContextComponent {
    fun getSharedPreferenceSpecific(): SharedPreferenceManagerSpecific

    fun inject(application: MyApplication)

    fun inject(application: MainActivity)
}

MyApplication.kt

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val component = DaggerContextComponent.builder().build()
        val sharedPreference = component.getSharedPreferenceSpecific()
    }
}

SharedPreferenceManagerSpecific.kt

public class SharedPreferenceManagerSpecific() {
    lateinit var myContext: Context

    @Inject constructor(context: Context) : this() {
        myContext = context
    }

    fun saveIntoSharedPreferences() {
    ...
    }
}
英文:

I just started using dagger2 and in spite of having read and documented myself to get the main ideas, I don't understand which would be the proper way of injecting the application's context.

I know that there are similar questions like this or this but this uses AndroidInjector and I'm getting even more lost. What I would like to understand is once the ContextComponent has been initialised and is a Singleton, how can I retrieve the instance of ContextComponent (that contains the Application's context) in order to call ContextComponent.getSharedPreferenceSpecific() and get an instance of SharedPreferenceManagerSpecific initialised with the Application's context?

The are the classes I have created, SharedPreferenceManagerSpecific it's just to understand how to inject a context to a class.

The error I get when the code of activity is executed i:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.amgdeveloper.articleReader/com.amgdeveloper.articleReader.ui.MainActivity}: java.lang.IllegalStateException: com.amgdeveloper.articleReader.dagger.ContextModule must be set
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)

ContextModule.kt

@Module
class ContextModule(private val app: Application) {

    @Provides
    @Singleton
    fun provideContext(): Context = app

}

ContextComponent.tk

@Singleton
@Component(modules = [ContextModule::class])
interface ContextComponent {
    fun getSharedPreferenceSpecific ():SharedPreferenceManagerSpecific

    fun inject (application: MyApplication)

    fun inject (application: MainActivity)

MyApplication.kt

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val component = DaggerContextComponent.builder().build()
        val sharedPreference = component.getSharedPreferenceSpecific()
    }
}

SharedPreferenceManagerSpecific.kt

public class SharedPreferenceManagerSpecific () {
    lateinit var myContext : Context

    @Inject constructor( context: Context) : this() {
        myContext=context
    }

    fun saveIntoSharedPreferences(){
    ...
    }

}

答案1

得分: 1

Dagger并不在任何地方存储组件实例,甚至不会存储@Singleton组件实例:在Dagger看来,@Singleton只是另一种范围而已。为了在你的Application类中创建一个组件并在Activity类中使用它,你需要自己将其存储在某个地方。

在大多数使用Dagger的Android应用中,组件存储在Application中:

class MyApplication : Application() {
    
    // 如果你不使用任何ContentProviders,你可以在onCreate中设置一个lateinit var。
    val component by lazy {
        DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
    }
    
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val component = (application as MyApplication).component
        val sharedPreference = component.getSharedPreferenceSpecific()
    }

}
英文:

Dagger doesn't store component instances anywhere. Not even @Singleton components: as far as Dagger is concerned, @Singleton is just another scope. In order to create a component in your Application class and use it in your Activity class, you will need to store it somewhere yourself.

In most Android apps using Dagger, the component is stored in the Application:

class MyApplication : Application() {
    
    // You could set a lateinit var in onCreate instead
    // if you don't use any ContentProviders.
    val component by lazy {
        DaggerContextComponent.builder().contextModule(ContextModule(this)).build()
    }
    
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val component = (application as MyApplication).component
        val sharedPreference = component.getSharedPreferenceSpecific()
    }

}

huangapple
  • 本文由 发表于 2020年9月23日 03:05:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/64016202.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定