0

My app is built with a Single Activity and it is feature-based multi-module. All UI is built using composable.

I want to create a custom scope for feature A. When the feature's journey is completed, its scope must be destroyed.

@Scope
@MustBeDocumented
@Retention(value = AnnotationRetention.RUNTIME)
annotation class MyCustomScope

component

@MyCustomScope
@DefineComponent(parent = SingletonComponent::class)
interface MyCustomComponent

@DefineComponent.Builder
interface MyCustomComponentBuilder {
    fun provideEmployee(@BindsInstance employee: Employee?): MyCustomComponentBuilder
    fun build(): MyCustomComponent
}

Employee interface

interface EmployeeInterface {
    fun employee() : Employee
}

class EmployeeInterfaceImpl @Inject constructor(): EmployeeInterface {
    override fun employee(): Employee {
        return Employee()
    }
}

Entry Point

@EntryPoint
@InstallIn(MyCustomComponent::class)
interface MyCustomEntryPoint {
    fun getEmployee(): EmployeeInterface
}

Module

@Module
@InstallIn(MyCustomComponent::class)
interface EmployeeModule {
    @MyCustomScope
    @Binds
    fun provideEmployeeInterface(employeeInterfaceImpl: EmployeeInterfaceImpl) : EmployeeInterface
}

Now using the employe in my viewmodel

@HiltViewModel
class AViewModel @Inject constructor(
    private val person: Person,
    private val componentManager: CustomComponentManager
) : ViewModel() {

    init {
        componentManager.setEmployee(Employee())
        val employee =  EntryPoints.get(componentManager, MyCustomEntryPoint::class.java).getEmployee()
        Log.d(
            "Test", "CVM Person: $person Hashcode: ${person.hashCode()} && Employee: $employee " +
                "Hashcode: ${employee.hashCode()}"
        )
    }
}

SecondViewmodel

@HiltViewModel
class BViewModel @Inject constructor(
    private val person: Person,
    private val componentManager: CustomComponentManager
) : ViewModel() {
   
 private val employee =
 EntryPoints.get(componentManager, MyCustomEntryPoint::class.java).getEmployee()
    
    init {
            Log.d(
            "Test", "DVM Person: $person Hashcode: ${person.hashCode()} && Employee: $employee " +
                "Hashcode: ${employee.hashCode()}"
        )
    }

    override fun onCleared() {
        componentManager.invalidatedEmployee()
        super.onCleared()
    }
}

CustomComponentManager

@Singleton
class CustomComponentManager @Inject constructor(
    private val componentBuilder:
    MyCustomComponentBuilder
) :
    GeneratedComponentManager<MyCustomComponent> {
    private var component = componentBuilder
        .provideEmployee(null)
        .build()

    fun setEmployee(employee: Employee) {
        component = componentBuilder
            .provideEmployee(employee)
            .build()
    }

    fun invalidatedEmployee() {
        component = componentBuilder
            .provideEmployee(null)
            .build()
    }

    override fun generatedComponent(): MyCustomComponent {
        return component
    }
}

Using the singleton annotation on the ComponentManager class makes the class singleton.

When I entered AViewModel I set the employee data as it is singleton hence I got the same employee instance on BViewModel.

My App Journey Home -> A Screen -> B Screen. After completing the A and B screen journey and coming back to the home screen. Will Dagger hold the CustomComponentManager instance? If yes, I want to destroy its instance when I finish my A->B->Home screen journey.

How can I achieve this?

I have followed Hilt Multi Module and Dagger Multi Module.

Shaon
  • 2,496
  • 26
  • 27

0 Answers0