I'm looking for a way to pass configuration input to a factory which is derived from a base class and holding different input parameters depending on that derived class for that factory.
I'm struggling to find a good way to implement this. So let me show what I've currently got and where the problem is:
class ExampleFragmentFactoryImpl @Inject constructor(
private val providers: List<ExampleFragmentProvider<out ExampleInput>>
): ExampleFragmentFactory {
@Suppress("UNCHECKED_CAST")
override suspend fun <T: ExampleInput> create(
pageType: T
): Fragment {
providers.forEach { provider ->
try {
val typesafeProvider = provider as? ExampleFragmentProvider<T>
typesafeProvider?.let {
return it.provide(pageType)
}
} catch (e: ClassCastException) {
// This try-except-block shall be avoided.
}
}
throw IllegalStateException("could not create Fragment for pageType=$pageType")
}
}
Here the factory interface...
interface ExampleFragmentFactory {
suspend fun <T : ExampleInput> create(
pageType: T
): Fragment
}
Now the provider interface...
interface ExampleFragmentProvider<T: ExampleInput> {
suspend fun provide(
pageType: T
) : Fragment
}
the input class...
sealed class ExampleInput {
object NotFound : ExampleInput()
object WebView : ExampleInput()
data class Homepage(
val pageId: String
) : ExampleInput()
}
and finally a provider implementation:
internal class ExampleHomepageProvider @Inject constructor() :
ExampleFragmentProvider<ExampleInput.Homepage> {
override suspend fun provide(pageType: ExampleInput.Homepage): Fragment {
TODO()
}
}
As commented above, it's really bad that try-except is necessary in the factory. There should be nice way of how to achieve this without try-except. Unfortunately, due to type erasure, it's not possible to check the type before casting. Working with reified types afaik is not possible using polymorphic code.
Another possible solution could be to avoid using generics and casting to the required input type within the providers provide()
method -- but that's not really nice, too.
Do you have any suggestions how I can improve this kind of factory?