如何在 Android 中通过 ViewModel 类在 Activity 和 Fragment 之间共享数据? [英] How to Share Data between Activity and Fragment via ViewModel Class in Android?

查看:128
本文介绍了如何在 Android 中通过 ViewModel 类在 Activity 和 Fragment 之间共享数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以传递在 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;start_time_str 并且它已经被初始化为 new MutableLiveData<>();

In ViewModel Class, I have MutableLiveData<String> start_time_str and it has been initialized as new MutableLiveData<>();

我想在Activity类中使用void send_StartTime(String start_Time)函数来设置参数String start_Time的值并调用start_time_str在片段类中.

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 并将字符串值设置为我的 TextView.我认为 start_time_str 已经通过 timeTableViewModel.send_StartTime(start_time_str); 的函数在活动类中成功设置,因为 Toast.maketext 就像一个魅力.但是 TextView 没有显示任何内容.我已经测试过文本颜色不是白色的,因此如果正确调用字符串值,它应该会出现在屏幕上. 如果您有任何建议,我很乐意听取您的建议.非常感谢.

In the Fragment class I call get_StartTime() function to get start_time_str and set the String value to my TextView. I think the start_time_str has been successfully set by function of timeTableViewModel.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 ,但这不是正确的方法.您应该使用 ViewModelProvider 或 Google 团队创建的扩展方法.

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);

将正确的上下文传递给 ViewModelProvider 构造函数调用很重要.如果您在片段中并且您将只使用 getContext() 而不是 getActivity(),您将不会获得与在 Activity 中创建的实例相同的实例.您将创建一个 ViewModel 的新实例,该实例的范围仅在片段生命周期内.所以重要的是在两个部分的活动上下文中使用以获得相同的实例.

It is important to pass the correct context to ViewModelProvider constructor 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 的同一 Activity 中.

Is important that your fragment is located inside the same activity that is using this ViewModel.

但是谷歌的人通过一些扩展方法让我们更容易.但据我所知,他们只在 Kotlin 课程中工作.所以如果你有 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆