Created
March 30, 2018 17:52
-
-
Save bleeding182/3de7151949090f5f0e33b6cd7ca37cf4 to your computer and use it in GitHub Desktop.
Dagger 2 `@PerScreen` scope surviving configuration change
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class App : Application() { | |
@Inject | |
lateinit var applicationInjector: ApplicationInjector | |
override fun onCreate() { | |
super.onCreate() | |
DaggerAppComponent.create().inject(this) | |
registerActivityLifecycleCallbacks(applicationInjector) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Singleton | |
@Component(modules = [ScreenModule::class]) | |
interface AppComponent { | |
fun inject(app: App) | |
fun getBinding(): Map<Class<out Activity>, Provider<ProvidesActivityInjectorFactories.Builder>> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Singleton | |
class ApplicationInjector @Inject constructor( | |
private val injectorFactories: Map<Class<out Activity>, @JvmSuppressWildcards Provider<ProvidesActivityInjectorFactories.Builder>> | |
) : Application.ActivityLifecycleCallbacks { | |
//region < Unused callback methods > | |
override fun onActivityPaused(activity: Activity) = Unit | |
override fun onActivityResumed(activity: Activity) = Unit | |
override fun onActivityStarted(activity: Activity) = Unit | |
override fun onActivityDestroyed(activity: Activity) = Unit | |
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) = Unit | |
//endregion | |
/** | |
* Map of components that survive a configuration change. | |
*/ | |
private val screenComponents: MutableMap<Class<out Activity>, ProvidesActivityInjectorFactories> = HashMap() | |
override fun onActivityStopped(activity: Activity) { | |
if (activity.isFinishing) { | |
// remove finished activity component | |
screenComponents.remove(activity.javaClass) | |
} | |
} | |
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { | |
val screenComponent: ProvidesActivityInjectorFactories = screenComponents[activity.javaClass] | |
?: injectorFactories[activity.javaClass]!!.get().build().also { | |
screenComponents[activity.javaClass] = it | |
} | |
@Suppress("UNCHECKED_CAST") | |
val activityInjectorFactory: AndroidInjector.Factory<Activity> = (screenComponent.provideInjectors()[activity.javaClass] as AndroidInjector.Factory<Activity>) | |
activityInjectorFactory.create(activity).inject(activity) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@PerScreen | |
class ScreenRandom @Inject constructor() { | |
val random = Random().nextInt() | |
} | |
@PerActivity | |
class ActivityRandom @Inject constructor() { | |
val random = Random().nextInt() | |
} | |
class MainActivity : AppCompatActivity() { | |
@Inject | |
lateinit var screenRandom: ScreenRandom | |
@Inject | |
lateinit var activityRandom: ActivityRandom | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
label.text = "This screens random number is:\n${screenRandom.random}\n\nThis activities random number is:\n${activityRandom.random}" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Module(subcomponents = [MainScreenSubComponent::class]) | |
interface ScreenModule { | |
@Multibinds | |
fun screenInjectorFactories(): Map<Class<out Activity>, ProvidesActivityInjectorFactories.Builder> | |
@Binds | |
@IntoMap | |
@ActivityKey(MainActivity::class) | |
fun bindMainScreenSubComponent(builder: MainScreenSubComponent.Builder): ProvidesActivityInjectorFactories.Builder | |
} | |
interface ProvidesActivityInjectorFactories { | |
fun provideInjectors(): Map<Class<out Activity>, AndroidInjector.Factory<out Activity>> | |
interface Builder { | |
fun build(): ProvidesActivityInjectorFactories | |
} | |
} | |
@PerScreen | |
@Subcomponent(modules = [MainScreenModule::class]) | |
interface MainScreenSubComponent : ProvidesActivityInjectorFactories { | |
@Subcomponent.Builder | |
abstract class Builder : ProvidesActivityInjectorFactories.Builder | |
} | |
@Module(subcomponents = [MainActivitySubComponent::class]) | |
interface MainScreenModule { | |
@Binds | |
@IntoMap | |
@ActivityKey(MainActivity::class) | |
fun bindMainActivityInjectorFactory(builder: MainActivitySubComponent.Builder): AndroidInjector.Factory<out Activity> | |
} | |
@PerActivity | |
@Subcomponent | |
interface MainActivitySubComponent : AndroidInjector<MainActivity> { | |
@Subcomponent.Builder | |
abstract class Builder : AndroidInjector.Builder<MainActivity>() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Scope | |
@MustBeDocumented | |
@Retention(AnnotationRetention.RUNTIME) | |
annotation class PerActivity |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Survives orientation change. | |
*/ | |
@Scope | |
@MustBeDocumented | |
@Retention(AnnotationRetention.RUNTIME) | |
annotation class PerScreen |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment