#android #android-fragments #mvvm #android-databinding #android-mvvm
#Android #android-фрагменты #mvvm #android-привязка данных #android-mvvm
Вопрос:
Я использую DataBinding
и следую архитектуре MVVM, теперь я застрял на том, как добавить новый фрагмент, ViewModel
поскольку нам нужно определенное событие щелчка ViewModel
. Вот мой MainViewModel
класс
public class MainViewModel {
private Context context;
public MainViewModel (Context context) {
this.context = context;
}
public void onClick(View v) {
}
}
вот мой xml, в котором я определил событие щелчка
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewmodel"
type="com.example.MainViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{viewmodel::onClick}"
android:text="click me"/>
</RelativeLayout>
</layout>
теперь, как я могу получить supportFragmentManager
или childFragmentManager
из моего класса ViewModel? Я пытался использовать activity.getSupportFragmentManager()
and activity.getChildFragmentManager()
, но у него нет такого метода.
Я знаю, что мы можем добавить фрагмент со следующим кодом
getActivity().getSupportFragmentManager().beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out).
add(R.id.container, fragment, "").addToBackStack("main").commit();
но как это сделать в ViewModel
классе
Ответ №1:
Поскольку у вас есть свой Context
доступный, у вас есть две возможности:
public class MainViewModel {
private Context context;
public MainViewModel (Context context) {
this.context = context;
}
public void onClick(View v) {
//use context:
((AppCompatActivity) context).getSupportFragmentManager();
//OR use the views context:
if(v.getContext() instanceof AppCompatActivity) {
((AppCompatActivity) v.getContext()).getSupportFragmentManager();
}
}
}
Может быть полезно проверить, является ли контекст экземпляром вашей активности (например MainActivity
) или AppCompatActivity
, или, если это null
так, перед вызовом любого метода.
Комментарии:
1. Плохой практикой является сохранение контекста из представления в ViewModel
2. @kazimad вы правы, именно поэтому MVVM был создан в первую очередь, а не для хранения ссылок на материалы, связанные с Android (view), в ViewModel.
3. @MeHdi у меня похожая проблема, что бы вы тогда предложили?
4. @LeNguyenDuyAnh Не могли бы вы объяснить подробнее? Вы хотите, чтобы какой-то фрагмент был добавлен в backstack?
Ответ №2:
Я не знаю, возможно ли это, но вот что я предлагаю:
Определите интерфейс и позвольте действию или фрагменту реализовать этот интерфейс
public interface FragmentProvider {
void showFragment(...);
}
Передайте экземпляр FragmentProvider в вашу ViewModel
public class MainViewModel {
private Context context;
private FragmentProvider provider;
public MainViewModel (FragmentProvider provider) {
this.provider = provider;
}
public void onClick(View v) {
// delegate the action
provider.showFragment(...);
}
}
Комментарии:
1. да, это доступный способ, но я не уверен, будет ли это хорошей идеей или нет при работе с mvvm.
2. Я хотел бы согласиться с идеей EventBus, что это лучшее решение, чем первый принятый ответ здесь.
3.Я хотел бы согласиться с идеей EventBus, что это лучшее решение, чем первый принятый ответ здесь.