【问题标题】:How to Share Data between Activity and Fragment via ViewModel Class in Android?如何在 Android 中通过 ViewModel 类在 Activity 和 Fragment 之间共享数据?
【发布时间】:2020-03-27 11:53:04
【问题描述】:

我想知道是否可以传递一个在 Activity 类中声明的 String 数据并将 String 数据传递给 ViewModel 类,然后将数据传递给 Fragment 类。

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&lt;String&gt; start_time_str,它已被初始化为 new MutableLiveData&lt;&gt;();

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

活动类

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

【问题讨论】:

    标签: android mvvm viewmodel android-livedata mutablelivedata


    【解决方案1】:

    这实际上取决于您如何创建ViewModel 实例。现在您正在通过其构造函数创建ViewModel,但这不是正确的方法。您应该使用 ViewModelProvider 或 Google 团队创建的扩展方法。

    如果你选择ViewModelProvider,你应该这样做:

    TimeTableViewModel viewModel = new ViewModelProvider(this).get(TimeTableViewModel.class);
    

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

    活动部分:

    TimeTableViewModel viewModel = new ViewModelProvider(this).get(TimeTableViewModel.class);
    

    片段部分:

    TimeTableViewModel viewModel = new ViewModelProvider(getActivity()).get(TimeTableViewModel.class);
    

    重要的是您的片段位于使用此ViewModel 的同一活动中。

    但是 Google 的一些人通过一些扩展方法让我们变得更容易了。但据我所知,他们只在 Kotlin 课程中工作。所以如果你有 Kotlin 代码,你可以像这样声明你的ViewModel

    private val quizViewModel: TimeTableViewModel by activityViewModels()
    

    对于范围为ViewModel 的片段,您需要编写如下内容:

    private val quizViewModel: TimeTableViewModel by viewModels()
    

    但是您必须将 Kotlin ktx 依赖项添加到您的项目 build.gradle 文件中。比如这样:

    implementation 'androidx.fragment:fragment-ktx:1.1.0'
    

    【讨论】:

    • 感谢您的回答。由于片段不在我的活动类中,我无法使用 ViewModel 类共享数据,因此我创建了新片段然后替换为活动类。它工作得很好。非常感谢。
    • 如果您使用导航组件,您还可以通过导航图来确定 ViewModel 的范围,如下所示:val myViewModel: TimeTableViewModel by navGraphViewModels(R.id.navigation_graph)。很高兴我能帮助你。 :)
    • 这样做有什么好处?
    • 你指的是哪一部分?导航范围的 ViewModel?
    • 根据 Android 团队的最新指导,我们通常将 Single Activity 与 Navigation 组件结合使用来构建我们的应用程序。如果是这种情况,那么如果我们使用 Activity ViewModel,我们实际上是在创建一个贯穿整个应用程序的单例。为避免这种情况,我们可以将我们的应用程序分解为不同的导航,并通过导航用例正确地确定逻辑组件的范围。例如,我们不需要登录用户的主屏幕中的一些 OnboardingManager。
    【解决方案2】:

    如果您使用的是 Android 架构并希望在您的fragments 中分享activityViewModel

    要在fragment 中获取viewModels,请使用以下代码:

    private val fragmentViewModel: Fragment1ViewModel by viewModels()
    private val activityViewModel: MainActivityViewModel by activityViewModels()
    

    MainActivity 中使用以下代码:

    private val activityViewModel: MainActivityViewModel by viewModels()
    

    【讨论】:

      【解决方案3】:

      我找到了解决这个问题的最简单方法,而不是把所有者作为“this”改为 getActivity()。

      
          @Override
              public void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  if (mvm == null) {
                      mvm = new ViewModelProvider(getActivity()).get(CounterFgViewModel.class);
                  }
              }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多