Как обмениваться данными между действием и фрагментом через класс ViewModel в Android? - PullRequest
0 голосов
/ 27 марта 2020

Интересно, можно ли передать данные String, объявленные в классе Activity, передать данные 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<String> start_time_str, и он был инициализирован как new MutableLiveData<>();

Я хотел бы использовать функцию void send_StartTime(String start_Time) в классе Activity для установки значения аргумента String start_Time и вызовите 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); в классе деятельности, потому что Toast.maketext работает как шарм. Однако TextView ничего не показывает. Я проверил, что цвет текста не белый, поэтому, если строковое значение вызывается правильно, оно должно появиться на экране. Если у вас есть предложения, я хотел бы услышать ваш совет. Большое спасибо

enter image description here

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

Это действительно зависит от того, как вы создаете свой экземпляр ViewModel. Теперь вы создаете ViewModel по его конструктору, но это не совсем правильно. Вы должны использовать ViewModelProvider или методы расширения, которые были созданы командой Google.

Если вы go используете ViewmodelProvider, вы должны сделать это следующим образом:

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

Важно передать правильный контекст в вызов метода of. Если вы находитесь во фрагменте и просто используете 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'
0 голосов
/ 27 марта 2020

Создайте модель представления, подобную этой, не используйте new для создания нового vm для фрагмента,

val  viewmodel = ViewModelProviders.of(this).get(MyFavouritesViewModel.class);

Это вернет тот же экземпляр, который активность использует и во фрагменте

...