如何在Android中通过ViewModel Class在Activity和Fragment之间共享数据?

How to Share Data between Activity and Fragment via ViewModel Class in Android?

我想知道是否可以将在 Activity class 中声明的字符串数据传递给 ViewModel class 然后将数据传递给片段 class.

ViewModel Class

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 Class 中,我有 MutableLiveData<String> start_time_str 并且它已被初始化为 new MutableLiveData<>();

我想在 Activity class 中使用 void send_StartTime(String start_Time) 函数来设置参数 String start_Time 的值并在 Fragment [=55] 中调用 start_time_str =].

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

片段Class

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

在片段 class 中,我调用 get_StartTime() 函数来获取 start_time_str 并将字符串值设置为我的 TextView。我认为 start_time_str 已通过 Activity Class 中的 timeTableViewModel.send_StartTime(start_time_str); 的功能成功设置,因为 Toast.maketext 就像一个魅力。 但是 TextView 没有显示任何内容。我已经测试过 Text Color is not white 所以如果字符串值被正确调用,它应该出现在屏幕上。 如果您有任何建议,我很想听听您的建议。 非常感谢。

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

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

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

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

Activity部分:

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

片段部分:

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

重要的是您的片段位于使用此 ViewModel 的同一 activity 内。

但是 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'

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

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

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

并在 MainActivity 中使用以下代码:

private val activityViewModel: MainActivityViewModel by viewModels()

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


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

我正在使用科特林语言 我使用与教程相同但不工作 下面是如何声明我的 ViewModel

的示例代码

在build.gradle中添加依赖:

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

Activity的例子class

class HomepageActivity : AppCompatActivity() {
    private lateinit var sharedViewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityHomepageBinding.inflate(layoutInflater)
        setContentView(binding.root)

        sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
        sharedViewModel.isMenuOpen.observe(this, {
            onMenuOpen(it)
        })
    }

片段中的示例 class

class HomeFragment : Fragment() { private lateinit var sharedViewModel: SharedViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    sharedViewModel = activity!!.run{
        ViewModelProvider(this).get(SharedViewModel::class.java)
    }
}