Я пытаюсь понять MVVM (это очень ново для меня), и я понял, как наблюдать за LiveData с помощью Room и ViewModel. Теперь я столкнулся с проблемой.
У меня есть запрос Room, для которого требуется параметр, и именно так я начинаю наблюдать за LiveData в onCreate в MainActivity.
String color = "red";
myViewModel.getAllCars(color).observe(this, new Observer<List<Car>>() {
@Override
public void onChanged(@Nullable List<Car> cars) {
adapter.setCars(cars);
}
});
Используя этот код, я получаю список «красных» автомобилей и заполняю RecyclerView списком.
Теперь к моему вопросу - есть ли способ изменить переменную color внутри метода getAllCars (например, нажатием кнопки) и повлиять на наблюдателя, чтобы он возвращал новый список? Если я просто изменю цветовую переменную, ничего не произойдет.
Как указано в этом ответе, ваше решение - Transformation.switchMap
От Сайт Android для разработчиков:
LiveData< Y > switchMap (LiveData< X > trigger, Function< X, LiveData< Y >> func)
Creates a LiveData, let's name it swLiveData, which follows next flow: it reacts on changes of trigger LiveData, applies the given function to new value of trigger LiveData and sets resulting LiveData as a "backing" LiveData to swLiveData. "Backing" LiveData means, that all events emitted by it will retransmitted by swLiveData.
В вашей ситуации это будет выглядеть примерно так:
public class CarsViewModel extends ViewModel {
private CarRepository mCarRepository;
private LiveData<List<Car>> mAllCars;
private LiveData<List<Car>> mCarsFilteredByColor;
private MutableLiveData<String> filterColor = new MutableLiveData<String>();
public CarsViewModel (CarRepository carRepository) {
super(application);
mCarRepository= carRepository;
mAllCars = mCarRepository.getAllCars();
mCarsFilteredByColor = Transformations.switchMap(
filterColor,
color -> mCarRepository.getCarsByColor(color)
);
}
LiveData<List<Car>>> getAllCars() { return mAllCars; }
LiveData<List<Car>> getCarsFilteredByColor() { return mCarsFilteredByColor; }
// When you call this function to set a different color, it triggers the new search
void setFilter(String color) { filterColor.setValue(color); }
}
Поэтому, когда вы вызываете метод setFilter из своего представления, изменение filterColor LiveData запускает Transformation.switchMap, который вызывает mRepository.getCarsByColor(c)), а затем обновляет результат запроса mCarsFilteredByColor LiveData. Следовательно, если вы наблюдаете этот список в своем представлении и устанавливаете другой цвет, наблюдатель получит новые данные.
Ваш код очень помог. Но есть проблема в строке: private LiveData<String> filterColor = new MutableLiveData<String>(); вместо private MutableLiveData<String> filterColor = new MutableLiveData<String>();, потому что LiveData'ssetValue() имеет защищенный доступ, а MutableLiveData'ssetValue() имеет открытый доступ.
@SayokMajumder ты прав, спасибо! Ответ отредактирован.
Помимо ответа @dglozano, один простой способ сделать это - наблюдать за color вместо наблюдения за list. И на valueChange из color получите новый список.
Пример:
В классе ViewModel сделайте это
MutableLiveData<String> myColor = new MutableLiveData<String>();
В Activity сделайте так:
button.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
myViewModel.myColor.setValue("newColor");
} });
myViewModel.myColor.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String newValue) {
// do this on dedicated thread
List<Car> updateList = myViewModel.getCarsByColor(newValue)
// update the RecyclerView
}
});
Примечание: 1. getCarsByColor() не нужно упаковывать как LiveData. Метод в Dao может возвращать List<Cars> вместо LiveData<List<Cars>>.
2. Не запускайте запросы к базе данных в основном потоке и вызывайте notifyDataSetChanged, чтобы обновить RecyclerView.
Не знаю, чего ты здесь пытаешься достичь. Почему вам нужно использовать наблюдателя для «наблюдения» за цветом, если вы уже знаете об изменении его значения с помощью метода onClick? В некотором смысле вы сами устанавливаете значение, а затем получаете то же самое через наблюдателя, что бессмысленно.
это было полезно для меня, когда мне приходилось извлекать данные из комнаты на основе различных вариантов сортировки, выбранных пользователем. Раньше я делал это очень необычным способом. Спасибо!