Can I do anything in this snippet to prevent the n...
# announcements
w
Can I do anything in this snippet to prevent the need from using a generic and passing in the
Class
as well?
Copy code
abstract class BaseViewModelFragment<T : ViewModel>(private val type: Class<T>) : BaseInjectedFragment() {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: T

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(type)
    }
}
🚫 1
i understand type erasure is a problem here i just don't now if there are other workarounds
w
It suggests something like:
Copy code
abstract class BaseViewModelFragment<T : ViewModel> : Fragment() {
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: T

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(
            (this.javaClass
                .genericSuperclass as ParameterizedType)
                .actualTypeArguments[0] as Class<T>
        )
    }
}
🤔 1
w
that must be reflection? haven't touched that before but im assuming so
is this a moment where its ok to use reflection? definately winds up with a cleaner result
w
I would not use like that, would explore and perhaps change to not need it.
w
how so @wbertan?
w
Good question...
Hey, again, I didn't tested:
Copy code
abstract class BaseViewModelFragment<T : ViewModel> : Fragment() {
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private lateinit var viewModel: T

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(viewModel::class.java)
    }
}
👀
👀 1
w
holy
hmmmmmmmmmm
w
Check this:
Copy code
bstract class BaseViewModelFragment<T : ViewModel> : Fragment() {
    lateinit var viewModelFactory: ViewModelProvider.Factory
    abstract val viewModel: T

    inline fun <reified K : ViewModel> asasMagic() = ViewModelProviders.of(this, viewModelFactory).get(K::class.java)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    }
}

class OtherViewModelFragment: BaseViewModelFragment<ViewModel>() {
    override val viewModel: ViewModel
        get() = asasMagic()
}
w
so that definately makes sense using reified just not as abstracted away with having to get the viewmodel
i think your other solution does work though as this snippet
Copy code
fun main() {
    Fuzz(3.0)
}

class Fuzz<T : Number>(init: T) {
    init {
        println(init::class.java)
    }
}
prints
class java.lang.Double
s
are reified generics in inline methods methods a possibility? (first and only thought, I didn’t really look at the problem in depth)
w
wound up doing this
Copy code
abstract class BaseViewModelFragment : BaseInjectedFragment() {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    /**
     * Lazily get the view model
     */
    inline fun <reified VM : ViewModel> viewModel() = lazy {
        ViewModelProviders.of(this, viewModelFactory).get(VM::class.java)
    }
}
so yeah basically the last thing recomended by you guys @Stephan Schroeder @wbertan
👍 2
and then in my fragments that extend
BaseViewModelFragment
I use
private val viewModel: HomeViewModel by viewModel()