room - Android ViewModel argumentos adicionales
view model android studio (3)
Debe tener una clase de fábrica para su ViewModel.
public class MyViewModelFactory implements ViewModelProvider.Factory {
private Application mApplication;
private String mParam;
public MyViewModelFactory(Application application, String param) {
mApplication = application;
mParam = param;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
return (T) new MyViewModel(mApplication, mParam);
}
}
Y al crear una instancia del modelo de vista, te gusta esto:
MyViewModel myViewModel = ViewModelProviders.of(this, new MyViewModelFactory(this.getApplication(), "my awesome param")).get(MyViewModel.class);
¿Hay alguna forma de pasar argumentos adicionales a mi constructor de AndroidViewModel
personalizado, excepto el contexto de la aplicación? Ejemplo:
public class MyViewModel extends AndroidViewModel {
private final LiveData<List<MyObject>> myObjectList;
private AppDatabase appDatabase;
public MyViewModel(Application application, String param) {
super(application);
appDatabase = AppDatabase.getDatabase(this.getApplication());
myObjectList = appDatabase.myOjectModel().getMyObjectByParam(param);
}
}
Y cuando quiero usar mi clase de ViewModel
personalizada, uso este código en mi fragmento:
MyViewModel myViewModel = ViewModelProvider.of(this).get(MyViewModel.class)
Así que no sé cómo pasar un ViewModel
String param
argumento adicional a mi ViewModel
personalizado. Solo puedo pasar el contexto de la aplicación, pero no argumentos adicionales. Realmente apreciaria cualquier ayuda. Gracias.
Edición: he añadido algún código. Espero que sea mejor ahora.
Escribí una biblioteca que debería hacer esto más sencillo y más limpio, sin necesidad de multibuntos o repeticiones de fábrica, mientras trabajo sin problemas con los argumentos de ViewModel que Dagger puede proporcionar como dependencias: https://github.com/radutopor/ViewModelFactory
@ViewModelFactory
class UserViewModel(@Provided repository: Repository, userId: Int) : ViewModel() {
val greeting = MutableLiveData<String>()
init {
val user = repository.getUser(userId)
greeting.value = "Hello, $user.name"
}
}
En la vista:
class UserActivity : AppCompatActivity() {
@Inject
lateinit var userViewModelFactory2: UserViewModelFactory2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
appComponent.inject(this)
val userId = intent.getIntExtra("USER_ID", -1)
val viewModel = ViewModelProviders.of(this, userViewModelFactory2.create(userId))
.get(UserViewModel::class.java)
viewModel.greeting.observe(this, Observer { greetingText ->
greetingTextView.text = greetingText
})
}
}
Para una fábrica compartida entre varios modelos de vista diferentes, extendería la respuesta de mlyko de esta manera:
public class MyViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private Application mApplication;
private Object[] mParams;
public MyViewModelFactory(Application application, Object... params) {
mApplication = application;
mParams = params;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass == ViewModel1.class) {
return (T) new ViewModel1(mApplication, (String) mParams[0]);
} else if (modelClass == ViewModel2.class) {
return (T) new ViewModel2(mApplication, (Integer) mParams[0]);
} else if (modelClass == ViewModel3.class) {
return (T) new ViewModel3(mApplication, (Integer) mParams[0], (String) mParams[1]);
} else {
return super.create(modelClass);
}
}
}
Y instanciando modelos de vista:
ViewModel1 vm1 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), "something")).get(ViewModel1.class);
ViewModel2 vm2 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), 123)).get(ViewModel2.class);
ViewModel3 vm3 = ViewModelProviders.of(this, new MyViewModelFactory(getApplication(), 123, "something")).get(ViewModel3.class);
Con diferentes modelos de vista teniendo diferentes constructores.