Android 使用ViewModel和update处理不同片段之间的数据
我试图实现一个datepicker片段,它必须将所选日期返回给调用它的片段(父片段)。我实现了一个接口,但似乎该接口只在活动中被调用,而不是在片段中被调用(即使我显式地调用它)。我用日志文件查过了 然后我继续使用ViewModel类来保存数据。现在的问题是,我能够在ViewModel类中存储数据,但我不知道在父片段中调用ViewModel函数的位置。在OnCreate/OnCreateView上调用它没有帮助,因为片段已经加载。在OnResume/OnAttach上调用它会使具有空指针引用的应用程序崩溃Android 使用ViewModel和update处理不同片段之间的数据,android,android-fragments,viewmodel,Android,Android Fragments,Viewmodel,我试图实现一个datepicker片段,它必须将所选日期返回给调用它的片段(父片段)。我实现了一个接口,但似乎该接口只在活动中被调用,而不是在片段中被调用(即使我显式地调用它)。我用日志文件查过了 然后我继续使用ViewModel类来保存数据。现在的问题是,我能够在ViewModel类中存储数据,但我不知道在父片段中调用ViewModel函数的位置。在OnCreate/OnCreateView上调用它没有帮助,因为片段已经加载。在OnResume/OnAttach上调用它会使具有空指针引用的应用
public class ShareData extends ViewModel{
private int year, month, day;
private String date;
public void getDate(int y, int m, int d)
{
Log.d("Viewmodel is", Integer.toString(year) + " " + Integer.toString(month) + " " + Integer.toString(day));
year = y;
month = m;
day = d;
}
public String setDate()
{
return (Integer.toString(year) + "-" + Integer.toString(month) + "-" + Integer.toString(day));
}
}
这是DatePicker对话框片段中的代码:
public void onDateSet(DatePicker view, int year, int month, int day) {
viewModel.getDate(year,month+1,day);
datePicked.onDatePicked(view, year, month+1, day);
// Do something with the date chosen by the user
}
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.operations_static_new, container, false);
name = view.findViewById(R.id.patient_name);
id = view.findViewById(R.id.patient_id);
date_textview = view.findViewById(R.id.date_static);
date_textview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmDatePicker(); //this opens fragment to choose date
}
});
model = ViewModelProviders.of(getActivity()).get(ShareData.class);
date_textview.setText(model.setDate());
}
这是我的父片段:
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.operations_static_new, container, false);
name = view.findViewById(R.id.patient_name);
id = view.findViewById(R.id.patient_id);
date_textview = view.findViewById(R.id.date_static);
date_textview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
confirmDatePicker(); //this opens fragment to choose date
}
});
model = ViewModelProviders.of(getActivity()).get(ShareData.class);
date_textview.setText(model.setDate());
}
我在哪里调用date_textview.setText,以便在日期选择器的textview上显示日期 我在您的ViewModel中没有看到任何LiveData,这说明您没有正确使用它。您应该做的是将ViewModel中的LiveData绑定到要更新的片段。在这之后,在观察ViewModel的任何片段中接收更改通知是很简单的 因此,首先,您的ViewModel应该如下所示:
// This will now notify the fragment that is observing of any changes made
public class SharedData extends ViewModel {
private int year, month, day;
private MutableLiveData<String> date = new MutableLiveData<>();
// This will notify observing fragments of changes
public void setDate(int y, int m, int d) {
year = y; month = m; day = d;
date.setValue(year + "-" + month + "-" + day);
}
// This is a factory method for getting the LiveData the fragment will bind to
public LiveData<String> getDate() {
return date;
}
}
与
viewModel.getDate().observe(这个,新的观察者(){
@凌驾
公共void onChanged(@Nullable String newDate){
//使用新数据更新视图
dateTextView.setText(newDate);
}
});
设置完成后,您可以从任何地方调用setDate(y,m,d),它将始终更新正在观察它的片段
通常在ActivityCreated上实例化ViewModel是个好主意,试试看。是的,我做到了。但是在我已经从dailogfragment中输入日期之后,必须调用textview.setText。现在,我已经通过调用按钮上的.setText来实现了另一个按钮的单击。这是一个糟糕的解决方案,但很好。我不完全理解,您可以将ViewModel声明为
private ViewModel model
,在创建的活动中实例化它,然后在其他地方实例化它。
viewModel.getDate().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String newDate) {
// Update your view with the new data
dateTextView.setText(newDate);
}
});