Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting unchecked cast warning while creating ViewModel factory

Tags:

android

I was creating a ViewmodelFactory so that I can use a ViewModel constructor which can accept arguments. However, I am getting "unchecked cast" warning on this line -

return (T) new clubPageViewModel(mDataSource);

How to fix this? or I am fundamentally wrong somewhere?

public class clubPageViewModelFactory implements ViewModelProvider.Factory {

    private final String mDataSource;

    public clubPageViewModelFactory(String dataSource) {
        mDataSource = dataSource;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        if (modelClass.isAssignableFrom(clubPageViewModel.class)) {
            return (T) new clubPageViewModel(mDataSource);
        }
        throw new IllegalArgumentException("Unknown ViewModel class");
    }    
}

Is there a way out?

like image 813
dexter2019 Avatar asked Jan 19 '19 08:01

dexter2019


2 Answers

One thing you can do is to suppress your warning using annotation for "Unchecked casts".

Check example :

@SuppressWarnings("unchecked") // This would be helpful for lint warnings for casts.
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
    if (modelClass.isAssignableFrom(clubPageViewModel.class)) {
        // Or better use here if it doesn't provides error @SuppressWarnings("unchecked")
        return (T) new clubPageViewModel(mDataSource);
    }
    throw new IllegalArgumentException("Unknown ViewModel class");
}

So, what does this @SuppressWarnings annotation do?

Basically, it indicates that the named compiler warnings should be suppressed in the annotated element (and in all program elements contained in the annotated element).

Note that the set of warnings suppressed in a given element is a superset of the warnings suppressed in all containing elements.

For example, if you annotate a class to suppress one warning and annotate a method to suppress another, both warnings will be suppressed in the method.

As a matter of style, programmers should always use this annotation on the most deeply nested element where it is effective. If you want to suppress a warning in a particular method, you should annotate that method rather than its class.

You can see more details here about this annotation.

like image 143
Jeel Vankhede Avatar answered Sep 22 '22 19:09

Jeel Vankhede


For who is looking for solution in Kotlin, please try with @Suppress("UNCHECKED_CAST") instead. Bellow is my sample ViewModelFactory

class ViewModelFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) :
    ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T =
        viewModels[modelClass]?.get() as T
}

I hope it will help everyone in the future.

like image 36
Chivorn Avatar answered Sep 21 '22 19:09

Chivorn