Как передать методы Фрагмента во ViewModel?
Мой фрагмент реализовывает методы интрефейса. Мне нужно передать эти методы в ViewModel
Методы интерфейса реализованные во Фрагменте:
@Override
public Note newNoteForEquals() {
Note newNoteForEquals = new Note();
newNoteForEquals.setId(note.getId());
newNoteForEquals.setTitle(editTextTitle.getText().toString());
newNoteForEquals.setDescription(editTextDescription.getText().toString());
newNoteForEquals.setDate(note.getDate());
return newNoteForEquals;
}
@Override
public String getTitleFromEditText() {
return editTextTitle.getText().toString();
}
@Override
public String getDescriptionFromEditText() {
return editTextTitle.getText().toString();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (note != null) {
if (!(newNoteForEquals().equals(startNote()))) {
viewModelCreateNote.createAlertDialog(getContext());
} else {
goHome();
}
} else {
goHome();
}
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), callback);
}
@Override
public void goHome() {
Navigation.findNavController(requireView()).navigate(R.id.home_dest);
}
Метод во ViewModel, где необходимо задействовать методы из фрагмента.
Я попытался реализовать это передав через конструктор ViewModel интерфейс фрагмента, но получил RuntimeExeption.
ICreateNoteView view;
private CreateNoteViewModel(ICreateNoteView view) {
this.view = view;
}
public void createAlertDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setMessage(R.string.save_the_changes)
.setCancelable(false)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (validation(view.getTitleFromEditText(),
view.getDescriptionFromEditText())) {
updateNote(view.newNoteForEquals());
view.goHome();
} else {
view.showMsgFailValid();
}
}
});
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
view.goHome();
}
}).create().show();
}
Заранее спасибо!
Ответы (1 шт):
Начнем с того, что если ваша ViewModel знает о каком-то интерфейсе View, то это уже не ViewModel, а скорее всего Presenter.
В чем принципиальная разница между MVP и MVVM подходом? Разница в том, что Presenter знает о существовании View (как минимум ее интерфейса), а ViewModel ничего не знает о существовании каких-либо View.
Взаимодействие между фрагментом и ViewModel проходит по принципу подписки. Т.е. фрагмент знает о существовании ViewModel и подписывается на ее изменения. Когда какие-либо изменения проходят в ViewModel, она постит свои изменения и все подписчики реагируют на них. Тем самым получается, что у нас может существовать 1 ViewModel и к примеру 10 фрагментов подписанных на нее.
Вот небольшой пример:
class TestViewModel extends ViewModel {
private MutableLiveData<String> messageLiveData = new MutableLiveData<>();
public LiveData<String> getMessageLiveData() {
return messageLiveData;
}
public void getMessage() {
// remote request
messageLiveData.postValue("Message");
}
}
class TestFragment extends Fragment {
// я тут пропустил ее инициализацию. Тут вы уже выберете свой способ, либо инжектить через DI либо через стандартную фабрику
private TestViewModel testViewModel;
// some code
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
testViewModel.getMessageLiveData().observe(this, this::handleMessage);
}
@Override
public void onStart() {
super.onStart();
testViewModel.getMessage();
}
private void handleMessage(String message) {
// some interraction with message
}
}
В этом примере ваша ViewModel не знает о своих подписчиках. Она постит свои данные в никуда, а подписчики сами решают как это обработать. Всякий раз когда во ViewModel будет изменена messageLiveData будет вызываться метод observe в View и там же вы можете обрабатывать изменение ваших данных.
Если же вам интересно все же MVP то я рекомендую вас посмотреть на эти 2 урока. Простой пример и более сложный пример.