Как использовать ViewModel для обновления TextView с вводом EditText? - PullRequest
0 голосов
/ 23 сентября 2019

У меня есть 3 вопроса, каждый из которых отображается фрагментом.После каждого вопроса есть фрагмент с TextView, ответ на который был введен в EditText предыдущего фрагмента вопроса.Я следовал инструкциям учебника, но это как-то не обновляет TextViews.Как использовать код, показанный здесь, чтобы ввод каждого вопроса отображался только в TextView следующего фрагмента?(фрагменты: вопрос 1 -> ответ 1 -> вопрос 2 -> ответ 2 -> вопрос 3 -> ответ 3)

Вот код первых двух фрагментов и ViewModel:

Фрагмент первого вопроса:

public class FragmentQuestion1 extends Fragment {

private Button btnNavFrag1;
private EditText mEditTextQuestion1;
private SharedViewModel viewModel;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_question_1, container, false);

    btnNavFrag1 = view.findViewById(R.id.btn_question1);

    mEditTextQuestion1 = view.findViewById(R.id.edit_text_question_1);

    btnNavFrag1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            viewModel.getAnswer(1);

            ((GameActivity)getActivity()).setViewPager(2);

        }
    });

    return view;
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
    viewModel.getAnswer(1).observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String answer) {
            viewModel.setAnswer(1, answer);
            mEditTextQuestion1.setText(answer);
        }
    });
}

Обзор первого ответа Фрагмент:

public class FragmentAnswer1 extends Fragment {

private View btnNavFragAns1;
private TextView tv_answer1;
private SharedViewModel viewModel;

@Nullable
@Override
public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_question_answer_1, container, false);

    btnNavFragAns1 = view.findViewById(R.id.next_question_1);

    tv_answer1 = view.findViewById(R.id.answer_player_1_text_view);

    btnNavFragAns1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            ((GameActivity)getActivity()).setViewPager(3);

        }
    });

    return view;
}

@Override
public void onActivityCreated(Bundle bundle) {
    super.onActivityCreated(bundle);

    viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
    viewModel.getAnswer(1).observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String answer) {
            viewModel.setAnswer(1, answer);
            tv_answer1.setText(answer);
        }
    });
}

Модель общего вида:

public class SharedViewModel extends ViewModel {


public HashMap<Integer, MutableLiveData<String>> answers = new HashMap<Integer, MutableLiveData<String>>(){{
    put(1, new MutableLiveData<String>());
    put(2, new MutableLiveData<String>());
    put(3, new MutableLiveData<String>());
}};



public MutableLiveData<String> getAnswer(int questionId) {
    return answers.get(questionId);
}

public void setAnswer(int questionId, String answer) {
    if (answers.get(questionId) != null) {
        answers.get(questionId).setValue(answer);
    }
}
}

1 Ответ

0 голосов
/ 23 сентября 2019

Это не сработает, потому что вы меняете ответ внутри обратного вызова onChange, поэтому этот обратный вызов никогда не будет вызываться.

viewModel.getAnswer(1).observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String answer) {
            viewModel.setAnswer(1, answer);
            tv_answer1.setText(answer);
        }
    });

Что я действительно рекомендую вам, так это использовать 2-способ связывания данных в этом случае.

Если вы не хотите, вы можете реализовать TextWatcher на ваш текст редактирования:

tv_answer1.addTextChangedListener(mTextWatcher)

Реализация так:

private TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence answer, int i, int i1, int i2) {
             viewModel.setAnswer(1, answer);
        }

        @Override
        public void afterTextChanged(Editable editable) {
        }
    };
...