简体   繁体   中英

Generic class type usage in Kotlin

I am trying to write a generic base activity, that specifies it's ViewModel type a generic parameter:

abstract class BaseActivity<T : ViewModel> : AppCompatActivity()

Now I am trying to write a lazy initialized property for my ViewModel:

val viewModel by lazy { ViewModelProviders.of(this, getFactory()).get(T) }

The error that is displayed is Type Parameter T is not an expression

Also using ::class or ::class.java did not help. Can anyone explain the problem?

EDIT: I tried to use a reified inline function like this:

inline fun <reified T : ViewModel?> AppCompatActivity.obtainViewModel(factory: ViewModelProvider.Factory): T {
    return ViewModelProviders.of(this, factory).get(T::class.java)
}

And used it like this:

abstract class BaseActivity<T> : AppCompatActivity() {
    val viewModel by lazy { obtainViewModel<T>(getFactory()) 
}

Now I get the error, that T cannot be used as a reified parameter.

EDIT2: The best solution so far seems to be this: Link , but its overhead to implement the abstract token in every extending class.

Your class has a type parameter T , which unfortunately gets erased at runtime. As a result, the call get(T) does not work (I guess the method expects a Class actually?).

You seem to have already noticed that and thus tried to fix it with encapsulating the handling into a method using reified type. Yet, you cannot pass T as a reified parameter since this type will already be erased when the reified -typed method is called. As a result, obtainViewModel<T> will not work either. What you can do, is using T for ordinary generic methods, which the following demonstrates:

class Typed<T> {
    val lazyProp by lazy {
        listOf<T>()
    }
}

maybe a bit late, but I guess this could be the elegant way to achieve it:

abstract class BaseActivity<T : ViewModel>(
    private var modelClass: Class<T>) : AppCompatActivity() {

    val viewModel by lazy { 
        ViewModelProviders.of(this, getFactory()).get(modelClass) 
    }

}

and then

class SampleActivity : BaseActivity<SampleViewModel>(SampleViewModel::class.java) {
    // use viewModel from here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM