Saltar al contenido

Android ViewModel no tiene constructor de argumento cero

Te traemos el arreglo a este rompecabezas, o por lo menos eso creemos. Si presentas inquietudes puedes dejarlo en el apartado de comentarios y sin tardanza

Al inicializar subclases de ViewModel utilizando ViewModelProviders, por defecto espera su UserModel clase para tener un constructor de cero argumentos. En tu caso, tu constructor tiene un argumento. MutableLiveData user

Una forma de solucionar esto es tener un constructor predeterminado sin argumentos para su UserModel

De lo contrario, si desea tener un constructor de argumentos distinto de cero para su clase ViewModel, es posible que deba crear un personalizado ViewModelFactory clase para inicializar su instancia de ViewModel, que implementará ViewModelProvider.Factory interfaz.

Todavía no he probado esto, pero aquí está el enlace a una excelente muestra de google para lo mismo: github.com/googlesamples/android-architecture-components. Específicamente, revise esta clase GithubViewModelFactory.java para el código Java y esta clase GithubViewModelFactory.kt para el código Kotlin correspondiente

ViewModelFactory que nos proporcionará un ViewModel correcto de ViewModelModule

public class ViewModelFactory implements ViewModelProvider.Factory 
    private final Map, Provider> viewModels;

    @Inject
    public ViewModelFactory(Map, Provider> viewModels) 
        this.viewModels = viewModels;
    

    @Override
    public  T create(Class modelClass) 
        Provider viewModelProvider = viewModels.get(modelClass);

        if (viewModelProvider == null) 
            throw new IllegalArgumentException("model class " + modelClass + " not found");
        

        return (T) viewModelProvider.get();
    

ViewModelModule es responsable de enlazar todas las clases de ViewModel en
Map, Provider> viewModels

@Module
public abstract class ViewModelModule 

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory); 
    //You are able to declare ViewModelProvider.Factory dependency in another module. For example in ApplicationModule.

    @Binds
    @IntoMap
    @ViewModelKey(UserViewModel.class)
    abstract ViewModel userViewModel(UserViewModel userViewModel);
    
    //Others ViewModels

ViewModelKey es una anotación para usar como key en el Mapa y parece

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey 
    Class value();

Ahora puede crear ViewModel y satisfacer todas las dependencias necesarias del gráfico

public class UserViewModel extends ViewModel 
    private UserFacade userFacade;

    @Inject
    public UserViewModel(UserFacade userFacade)  // UserFacade should be defined in one of dagger modules
        this.userFacade = userFacade;
    
 

Instanciando ViewModel

public class MainActivity extends AppCompatActivity 

    @Inject
    ViewModelFactory viewModelFactory;
    UserViewModel userViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ((App) getApplication()).getAppComponent().inject(this);

        userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);

    

Y no te olvides de añadir ViewModelModule en modules lista

@Singleton
@Component(modules = ApplicationModule.class, ViewModelModule.class)
public interface ApplicationComponent 
    //

En mi caso, ya que estoy usando HILT, faltaba una anotación sobre el Fragmento que tiene un ViewModel: @AndroidEntryPoint

@AndroidEntryPoint
class BestFragment : Fragment() { 
....

Por supuesto, en su clase ViewModel también necesita anotar con lo que necesita HILT: @ViewModelInject

class BestFragmentViewModel @ViewModelInject constructor(var userManager: UserManager) : ViewModel() 
....

Nos puedes añadir valor a nuestra información participando con tu experiencia en las explicaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *