【问题标题】:How to use ViewModel to update a TextView with the input of a EditText?如何使用 ViewModel 通过 EditText 的输入更新 TextView?
【发布时间】:2019-09-24 03:17:38
【问题描述】:

我有 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);
    }
}
}

【问题讨论】:

    标签: android android-fragments viewmodel


    【解决方案1】:

    这不起作用,因为您正在更改 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-way 数据绑定。

    不管你不想,你可以在编辑文本时实现一个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) {
            }
        };
    

    【讨论】:

    • 当我在我的问题片段中实现这个时,我在这一行得到一个错误:viewModel.setAnswer(1, answer); --> 第二个参数错误
    • 我设法将代码更改为此 viewModel.setAnswer(1, (String) answer);所以错误消失了,但是当我运行应用程序时,它在我在 EditText 中输入内容后崩溃,我得到这个 Log cat: java.lang.ClassCastException: android.text.SpannableStringBuilder cannot be cast to java.lang.String -- > 这是我更改行 viewModel.setAnswer(1, answer); 后得到的错误;
    • 您确实可以将 SpannableStringBuilder 转换为 String,您是否尝试过调用 SpannableStringBuilder#toString()?
    • 我不知道该怎么做
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多