Skip to content

Commit

Permalink
Initial integration of ContributesSubcomponent API
Browse files Browse the repository at this point in the history
  • Loading branch information
kingsleyadio committed Dec 16, 2021
1 parent ae93ca9 commit e4fff0c
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 120 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ buildscript {
repositories {
google()
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots")
}

dependencies {
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ androidxAppCompat = "1.3.1"
androidxCore = "1.7.0"
androidxFragment = "1.3.6"
androidxLifecycle = "2.4.0"
anvil = "2.3.9"
anvil = "2.3.8-CONTRIBUTE-SNAPSHOT"
dagger = "2.39.1"
kotlin = "1.5.31"
kotlinxCoroutines = "1.5.2"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
package com.deliveryhero.whetstone

import com.deliveryhero.whetstone.component.ActivityComponent
import com.deliveryhero.whetstone.component.ActivityComponentFactory
import com.deliveryhero.whetstone.component.ApplicationComponent
import com.deliveryhero.whetstone.component.ApplicationComponentFactory
import com.deliveryhero.whetstone.component.FragmentComponent
import com.deliveryhero.whetstone.component.FragmentComponentFactory
import com.deliveryhero.whetstone.component.ViewComponent
import com.deliveryhero.whetstone.component.ViewComponentFactory
import com.deliveryhero.whetstone.component.ViewModelComponent
import com.deliveryhero.whetstone.component.ViewModelComponentFactory
import com.deliveryhero.whetstone.scope.ActivityScope
import com.deliveryhero.whetstone.scope.ApplicationScope
import com.deliveryhero.whetstone.scope.FragmentScope
import com.deliveryhero.whetstone.scope.ViewModelScope
import com.deliveryhero.whetstone.scope.ViewScope
import com.squareup.anvil.annotations.ContributesTo
import com.squareup.anvil.annotations.MergeComponent
import com.squareup.anvil.annotations.MergeSubcomponent
import dagger.Binds
import dagger.Component
import dagger.Subcomponent


// DO NOT CHANGE THIS FILE.
//
Expand All @@ -35,67 +18,3 @@ public interface GeneratedApplicationComponent : ApplicationComponent {
@Component.Factory
public interface Factory : ApplicationComponentFactory
}

@MergeSubcomponent(ViewModelScope::class)
@SingleIn(ViewModelScope::class)
public interface GeneratedViewModelComponent : ViewModelComponent {

@Subcomponent.Factory
public interface Factory : ViewModelComponentFactory

@ContributesTo(ApplicationScope::class)
@dagger.Module(subcomponents = [GeneratedViewModelComponent::class])
public interface Module {

@Binds
public fun bindComponent(target: Factory): ViewModelComponentFactory
}
}

@MergeSubcomponent(ActivityScope::class)
@SingleIn(ActivityScope::class)
public interface GeneratedActivityComponent : ActivityComponent {

@Subcomponent.Factory
public interface Factory : ActivityComponentFactory

@ContributesTo(ApplicationScope::class)
@dagger.Module(subcomponents = [GeneratedActivityComponent::class])
public interface Module {

@Binds
public fun bindComponent(target: Factory): ActivityComponentFactory
}
}

@MergeSubcomponent(ViewScope::class)
@SingleIn(ViewScope::class)
public interface GeneratedViewComponent : ViewComponent {

@Subcomponent.Factory
public interface Factory : ViewComponentFactory

@ContributesTo(ActivityScope::class)
@dagger.Module(subcomponents = [GeneratedViewComponent::class])
public interface Module {

@Binds
public fun bindComponent(target: Factory): ViewComponentFactory
}
}

@MergeSubcomponent(FragmentScope::class)
@SingleIn(FragmentScope::class)
public interface GeneratedFragmentComponent : FragmentComponent {

@Subcomponent.Factory
public interface Factory : FragmentComponentFactory

@ContributesTo(ActivityScope::class)
@dagger.Module(subcomponents = [GeneratedFragmentComponent::class])
public interface Module {

@Binds
public fun bindComponent(target: Factory): FragmentComponentFactory
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots")
}
}

Expand Down
13 changes: 8 additions & 5 deletions whetstone/src/main/java/com/deliveryhero/whetstone/Whetstone.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.deliveryhero.whetstone

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.ContextWrapper
Expand All @@ -11,11 +12,11 @@ import androidx.lifecycle.Lifecycle
import com.deliveryhero.whetstone.component.ActivityComponent
import com.deliveryhero.whetstone.component.ApplicationComponent
import com.deliveryhero.whetstone.component.ApplicationComponentOwner
import com.deliveryhero.whetstone.component.ViewComponent
import com.deliveryhero.whetstone.injector.ContributesInjector
import dagger.MembersInjector
import java.util.concurrent.atomic.AtomicReference


/**
* Static utility methods for dealing with injection in standard Android components.
*/
Expand All @@ -24,6 +25,8 @@ public object Whetstone {

private val root = AtomicReference<ApplicationComponent>()

@SuppressLint("NewApi")
@InternalInjectApi // This method path is not used yet
public fun initialize(initializer: () -> ApplicationComponent) {
root.updateAndGet { component -> component ?: initializer() }
}
Expand All @@ -41,8 +44,8 @@ public object Whetstone {
public fun <T : Any> fromActivity(activity: Activity): T {
val contentView = activity.findViewById<View>(android.R.id.content)
return contentView.getTagOrSet(R.id.activityComponentId) {
fromApplication<ApplicationComponent>(activity.application)
.getActivityComponentFactory()
fromApplication<ActivityComponent.ParentComponent>(activity.application)
.createActivityFactory()
.create(activity)
} as T
}
Expand Down Expand Up @@ -96,8 +99,8 @@ public object Whetstone {

public fun inject(view: View) {
val activity = view.findActivity()
val injector = fromActivity<ActivityComponent>(activity)
.getViewComponentFactory()
val injector = fromActivity<ViewComponent.ParentComponent>(activity)
.createViewFactory()
.create(view)
.getMembersInjectorMap()[view.javaClass] as? MembersInjector<View>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package com.deliveryhero.whetstone.component

import android.app.Activity
import androidx.fragment.app.FragmentFactory
import com.deliveryhero.whetstone.SingleIn
import com.deliveryhero.whetstone.injector.MembersInjectorMap
import com.deliveryhero.whetstone.scope.ActivityScope
import com.deliveryhero.whetstone.scope.ApplicationScope
import com.deliveryhero.whetstone.viewmodel.ViewModelFactoryProducer
import com.squareup.anvil.annotations.ContributesSubcomponent
import com.squareup.anvil.annotations.ContributesTo
import dagger.BindsInstance
import dagger.Module
Expand All @@ -13,18 +16,28 @@ import dagger.multibindings.Multibinds
/**
* A Dagger component that has the lifetime of the [android.app.Activity].
*/
@ContributesSubcomponent(
scope = ActivityScope::class,
parentScope = ApplicationScope::class
)
@SingleIn(ActivityScope::class)
public interface ActivityComponent {
public fun getViewComponentFactory(): ViewComponentFactory
public fun getViewModelFactoryProducer(): ViewModelFactoryProducer
public fun getFragmentFactory(): FragmentFactory
public fun getMembersInjectorMap(): MembersInjectorMap
}

/**
* Interface for creating an [ActivityComponent].
*/
public interface ActivityComponentFactory {
public fun create(@BindsInstance activity: Activity): ActivityComponent
/**
* Interface for creating an [ActivityComponent].
*/
@ContributesSubcomponent.Factory
public interface Factory {
public fun create(@BindsInstance activity: Activity): ActivityComponent
}

@ContributesTo(ApplicationScope::class)
public interface ParentComponent {
public fun createActivityFactory(): Factory
}
}

@Module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import android.app.Application
import com.deliveryhero.whetstone.injector.MembersInjectorMap
import com.deliveryhero.whetstone.scope.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import com.deliveryhero.whetstone.SingleIn
import dagger.BindsInstance
import javax.inject.Singleton

/**
* A Dagger component that has the lifetime of the [android.app.Application].
*/
@ContributesTo(ApplicationScope::class)
@SingleIn(ApplicationScope::class)
@Singleton
public interface ApplicationComponent {
public fun getMembersInjectorMap(): MembersInjectorMap
public fun getActivityComponentFactory(): ActivityComponentFactory
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
package com.deliveryhero.whetstone.component

import com.deliveryhero.whetstone.SingleIn
import androidx.fragment.app.Fragment
import javax.inject.Provider
import com.deliveryhero.whetstone.scope.ActivityScope
import com.deliveryhero.whetstone.scope.FragmentScope
import com.squareup.anvil.annotations.ContributesSubcomponent
import com.squareup.anvil.annotations.ContributesTo

/**
* A Dagger component that has the lifetime of the [androidx.fragment.app.Fragment].
*/
@ContributesSubcomponent(
scope = FragmentScope::class,
parentScope = ActivityScope::class
)
@SingleIn(FragmentScope::class)
public interface FragmentComponent {
public fun getFragmentMap(): Map<Class<*>, Provider<Fragment>>
}

/**
* Interface for creating an [FragmentComponent].
*/
public interface FragmentComponentFactory {
public fun create(): FragmentComponent
/**
* Interface for creating an [FragmentComponent].
*/
@ContributesSubcomponent.Factory
public interface Factory {
public fun create(): FragmentComponent
}

@ContributesTo(ActivityScope::class)
public interface ParentComponent {
public fun createFragmentFactory(): Factory
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.deliveryhero.whetstone.component

import android.view.View
import com.deliveryhero.whetstone.SingleIn
import com.deliveryhero.whetstone.injector.MembersInjectorMap
import com.deliveryhero.whetstone.scope.ActivityScope
import com.deliveryhero.whetstone.scope.ViewScope
import com.squareup.anvil.annotations.ContributesSubcomponent
import com.squareup.anvil.annotations.ContributesTo
import dagger.BindsInstance
import dagger.Module
Expand All @@ -11,15 +14,26 @@ import dagger.multibindings.Multibinds
/**
* A Dagger component that has the lifetime of the [android.view.View].
*/
@ContributesSubcomponent(
scope = ViewScope::class,
parentScope = ActivityScope::class
)
@SingleIn(ViewScope::class)
public interface ViewComponent {
public fun getMembersInjectorMap(): MembersInjectorMap
}

/**
* Interface for creating an [ViewComponent].
*/
public interface ViewComponentFactory {
public fun create(@BindsInstance view: View): ViewComponent
/**
* Interface for creating an [ViewComponent].
*/
@ContributesSubcomponent.Factory
public interface Factory {
public fun create(@BindsInstance view: View): ViewComponent
}

@ContributesTo(ActivityScope::class)
public interface ParentComponent {
public fun createViewFactory(): Factory
}
}

@Module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,34 @@ package com.deliveryhero.whetstone.component
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import com.deliveryhero.whetstone.SingleIn
import com.deliveryhero.whetstone.scope.ApplicationScope
import com.deliveryhero.whetstone.scope.ViewModelScope
import com.squareup.anvil.annotations.MergeSubcomponent
import com.squareup.anvil.annotations.ContributesSubcomponent
import com.squareup.anvil.annotations.ContributesTo
import dagger.BindsInstance
import javax.inject.Provider

/**
* A Dagger component that has the lifetime of the [androidx.lifecycle.ViewModel].
*/
@MergeSubcomponent(ViewModelScope::class)
@ContributesSubcomponent(
scope = ViewModelScope::class,
parentScope = ApplicationScope::class
)
@SingleIn(ViewModelScope::class)
public interface ViewModelComponent {
public fun getViewModelMap(): Map<Class<*>, Provider<ViewModel>>
}

/**
* Interface for creating an [ViewModelComponent].
*/
public interface ViewModelComponentFactory {
public fun create(@BindsInstance savedStateHandle: SavedStateHandle): ViewModelComponent
/**
* Interface for creating an [ViewModelComponent].
*/
@ContributesSubcomponent.Factory
public interface Factory {
public fun create(@BindsInstance savedStateHandle: SavedStateHandle): ViewModelComponent
}

@ContributesTo(ApplicationScope::class)
public interface ParentComponent {
public fun createViewModelFactory(): Factory
}
}
Loading

0 comments on commit e4fff0c

Please sign in to comment.