如何通过Android中的ViewModel类在Activity和Fragment之间共享数据? [英] How to Share Data between Activity and Fragment via ViewModel Class in Android?
问题描述
我想知道是否可以传递在Activity类中声明的String数据,然后将String数据传递给ViewModel类,然后将数据传递给Fragment类.
I wondered if it's possible to pass a String data which has declared in Activity class and pass the String data to ViewModel class then pass the data to Fragment class.
ViewModel类
class TimeTableViewModel extends ViewModel {
private MutableLiveData<String> start_time_str = new MutableLiveData<>();
void send_StartTime(String start_Time){
start_time_str.setValue(start_Time);
}
LiveData<String> get_StartTime(){
return start_time_str;
}}
在ViewModel类中,我有
MutableLiveData< String>start_time_str
,它已被初始化为new MutableLiveData<>();
我想在Activity类中使用 void send_StartTime(String start_Time)
函数来设置参数 String start_Time
的值并调用 start_time_str
在Fragment类中.
I would like to use void send_StartTime(String start_Time)
function in Activity class to set value of argument String start_Time
and call the start_time_str
in Fragment class.
活动分类
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case android.R.id.home:
finish();
break;
case R.id.add_schedule_save:
String start_time_str = startTime.getText().toString();
Intent intent_restart0 = new Intent(TimeTable_Add_New_Schedule.this, MainActivity.class);
startActivity(intent_restart0);
TimeTableViewModel timeTableViewModel = new TimeTableViewModel();
timeTableViewModel.send_StartTime(start_time_str);
Toast.makeText(this,""+start_time_str,Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}
片段类
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TimeTableViewModel timeTableViewModel = new TimeTableViewModel();
timeTableViewModel.get_StartTime().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(String s) {
mon_textView_11.setText(s);
}
});
}
在Fragment类中,我调用
get_StartTime()
函数以获取start_time_str
并将String值设置为TextView.我认为start_time_str
已成功通过Activity类中的timeTableViewModel.send_StartTime(start_time_str);
的功能成功设置,因为Toast.maketext的工作原理很吸引人.但是,TextView没有显示任何内容.我测试过文本颜色"不是白色,因此如果正确调用了字符串值,则应该在屏幕上显示它.如果您有任何建议,我很想听听您的建议.非常感谢
In the Fragment class I call
get_StartTime()
function to getstart_time_str
and set the String value to my TextView. I think thestart_time_str
has been successfully set by function oftimeTableViewModel.send_StartTime(start_time_str);
in the Activity Class because of Toast.maketext is worked like a charm. However the TextView is not shown anything. I have tested Text Color is not white so that if the string value is correctly called, it should be appear on screen. If you have any suggestions, I would love to hear your advice. Thank you very much
推荐答案
这实际上取决于您如何创建ViewModel实例.现在,您要通过其构造函数创建ViewModel,但这不是正确的方法.您应使用由Google团队创建的ViewModelProvider或扩展方法.
It really depends on how do you create your ViewModel instance. Now you are creating ViewModel by its constructor, but that is not a proper way. You should use ViewModelProvider or extension methods that were created by Google team.
如果您使用ViewmodelProvider,则应该这样:
If you go with ViewmodelProvider you should do it like this:
TimeTableViewModel viewModel = new ViewModelProvider(this).get(TimeTableViewModel.class);
将正确的上下文传递给 of
方法调用非常重要.如果您处于片段状态,而只使用 getContext()
而不是 getActivity()
,则将不会获得与在Activity中创建的实例相同的实例.您将创建一个ViewModel的新实例,该实例的作用域仅在片段生命周期内.因此,在两个部分的活动上下文中使用它来获取相同的实例很重要.
It is important to pass the correct context to of
method call. If you are in fragment and you will just use getContext()
instead of getActivity()
, you will not get the same instance as it was created in Activity. You will create a new instance of ViewModel, that will be scoped only inside of fragment lifecycle. So it is important to use in both parts activity context to get the same instance.
活动部分:
TimeTableViewModel viewModel = new ViewModelProvider(this).get(TimeTableViewModel.class);
片段部分:
TimeTableViewModel viewModel = new ViewModelProvider(getActivity()).get(TimeTableViewModel.class);
重要的是,您的片段必须位于与使用此ViewModel相同的活动中.
Is important that your fragment is located inside the same activity that is using this ViewModel.
但是Google的家伙通过一些扩展方法使我们更容易了.但据我所知,它们仅在科特林班上工作.因此,如果您有kotlin代码,则可以像这样声明您的viewModel:
But guys at Google has make it easier for us with some extension methods. But as far as I know, they are working only in kotlin classes. So if you have kotlin code, you can declare your viewModel simply like this:
private val quizViewModel: TimeTableViewModel by activityViewModels()
对于Fragment范围的ViewModel,您需要编写如下内容:
For Fragment scoped ViewModel you need to write something like this:
private val quizViewModel: TimeTableViewModel by viewModels()
但是您必须将kotlin ktx依赖项添加到您的项目build.gradle文件中.例如这样的
But you have to add kotlin ktx dependency to your project build.gradle file. For example like this:
implementation 'androidx.fragment:fragment-ktx:1.1.0'
这篇关于如何通过Android中的ViewModel类在Activity和Fragment之间共享数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!