Hello, I need to create a list of anonymous functi...
# announcements
m
Hello, I need to create a list of anonymous function literals with receivers. What I got is
Copy code
private val fragmentInjectors = listOf<Pair<Class<out Fragment>, Fragment.() -> Unit>>(
            MainControlFragment::class.java to fun Fragment.(){ 
                (this as MainControlFragment).viewModelFactory = mockViewModelFactory
            }
    )
but ideally I would like something like
Copy code
private val fragmentInjectors = listOf<Pair<Class<out Fragment>, Fragment.() -> Unit>>(
            MainControlFragment::class.java to fun MainControlFragment.(){ 
               this.viewModelFactory = mockViewModelFactory
            }
    )
to avoid casting. But unfortunately compiler complains about
type inference failed, expected type mismatch
because of MainControlFragment and Fragment being different types. Anyone knows the right syntax?
m
I guess you could create
BaseFragment
that has view model factory
and then use that
m
good idea, thank you. but at the end of the day I don’t want to change the production code just to adjust for tests, would rather have a clean kotlin syntax solution
w
@Michal Klimczak seems like I got it working with
in
variance on the second parameter. Unfortunately
Pair
has
out
variance, so I had to use own pair type
Copy code
data class OwnPair<A, B>(
    val first: A,
    val second: B
)

private val fragmentInjectors = listOf<OwnPair<Class<out Fragment>, in Fragment.() -> Unit>>(
    OwnPair(MainControlFragment::class.java, fun MainControlFragment.() { // Can be different fragment types
        this.viewModelFactory
    })
)
💯 1
m
Seems great! Will check soon
w
But this does seem error-prone — you’re allowed to have different fragment types for both parameters of the pair type. Perhaps it would make sense to capture
Class<T>
and
T.() -> Unit
parameters in own pair class in the first place
m
yes, but the original one has that issue too. maybe this was the problem in the first place. I will give it another spin
cannot get it to work Created
Copy code
data class TypedBlock<T>(val clazz: Class<T>, val block: T.() -> Unit)
(I know, the name is lame, but w/e) and have something like
Copy code
listOf<TypedBlock<out Fragment>>(
            TypedBlock(
                    MainControlFragment::class.java,
                    fun MainControlFragment.() {
                        viewModelFactory = controlFragmentViewModelFactory
                    }
            )
But I need out variance in the
DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector<Fragment>(map)
Copy code
private fun createFakeFragmentsInjector(fragmentInjectorBlocks: List<TypedBlock<Fragment>>): DispatchingAndroidInjector<Fragment> {
        val map = fragmentInjectorBlocks
                .map { (clazz, block) ->
                    val injector = AndroidInjector<Fragment> { instance ->
                       
                        if (instance::class.java == clazz) {
                            instance.block()
                        }
                    }
                    clazz to AndroidInjector.Factory<Fragment> { injector }
                }
                .map { (clazz, factory) ->
                    clazz to (Provider { factory } as Provider<Factory<out Fragment>>)
                }
                .toMap()
                .toMutableMap()

        return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector<Fragment>(map)
    }