如何在不同的片段上使用 ModelView 来获取 EditText 的输入并将 TextView 设置为其值?
How to use ModelView on different Fragments to get the input of an EditText and set a TextView to its value?
所以基本上我想要实现的是将 EditText 的输入显示到另一个 Fragment 的 TextView 中。因此,用户回答一个问题并单击一个按钮,该按钮将他带到下一个片段,在 TextView 中应显示他的答案。由于我使用相同的方法有 3 个问题,因此我使用 ModelView 来实现此目的。由于我对编程比较陌生,所以我不知道这是否是我实现它的正确方法。非常感谢您的帮助!
这是我的视图模型:
public class SharedViewModel extends ViewModel {
private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();
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);
}
}
}
这是我第一个问题的第一个片段:
...
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(getViewLifecycleOwner(), new Observer<CharSequence>() {
@Override
public void onChanged(@Nullable CharSequence charSequence) {
mEditTextQuestion1.setText(charSequence);
}
});
}
这是我的答案概述片段,它显示在第一个问题片段之后,输入的答案应该替换 TextView 的默认值:
...
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(getViewLifecycleOwner(), new Observer<CharSequence>() {
@Override
public void onChanged(@Nullable CharSequence charSequence) {
tv_answer1.setText(charSequence);
}
});
}
}
Currently I get a NullPointerException at this line:
viewModel.getAnswer(1).observe(getViewLifecycleOwner(), new Observer<CharSequence>() {
在代码的这个特定部分:您没有为 get answer on key 1 设置任何值,您应该首先输入 MutableLiveData 键 "1":
viewModel.getAnswer(1)
首先你必须在 private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();
:
中输入一些东西作为键 1
answers.put(1, new MutableLiveData<String>());
之后您可以通过代码访问可变的实时数据:viewModel.getAnswer(1)
public void setAnswer(int questionId, String answer) {
if (answers.get(questionId) != null) {
answers.get(questionId).setValue(answer);
}
}
LiveData 初始化错误。
您正在访问它而无需在 OnActivityCreated() 中进行内部初始化。
首先初始化你的 mutablelivedata。
我将举例说明如何使用 ViewModel 解决您的问题。
视图模型
public class ViewModel_RoutineStartConnection extends AndroidViewModel{
public ViewModel_RoutineStartConnection(
@NonNull Application application) {
super(application);
}
private MutableLiveData<String> sAnswer = new MutableLiveData<>();
public void setAnswer(String sAnswer){
this.sAnswer.post(sAnswer);
}
public LiveData<String> getsAnswer(){
return this.sAnswer;
}
}
使用 EditText 设置值的片段
public class Fragment_getAnswer extends Fragment {
private ViewModel_RoutineStartConnection myViewModle;
private EditText edittext;
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root =
inflater.inflate(R.layout.YOURLAYOUT, container, false);
edittext = root.findViewById(R.id.YOURID);
edittext.setOnEditorActionListener(listener);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myViewModle = ViewModelProviders.of(getActivity()).get(ViewModel_RoutineStartConnection.class);
}
public TextView.OnEditorActionListener listener = new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_DONE) {
myViewModle.setAnswer(edittext.getText.toString);
}
return false;
}
};
}
片段读取值
public class Fragment_setAnswer extends Fragment {
private ViewModel_RoutineStartConnection myViewModle;
private TextView textview;
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root =
inflater.inflate(R.layout.YOURLAYOUT, container, false);
textview= root.findViewById(R.id.YOURID);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myViewModle = ViewModelProviders.of(getActivity()).get(ViewModel_RoutineStartConnection.class);
myViewModle.getsAnswer.observe(getViewLifecycleOwner(), obs_getsAnswer):
}
private Observer<String> obs_getsAnswer= new Observer<String>() {
@Override
public void onChanged(@Nullable String sAnswer) {
textview.setText(sAnswer);
}
};
}
要对所有答案使用此方法,我建议为每个答案添加一个 "id"。
所以当你设置 setAnswer("01" + answerText)
当您观察数据时,您可以使用:
switch(sAnswer.subString(0,3)){
case "01":
//set answer text for answer 1
break;
经过长时间的尝试,我找到了解决问题的正确方法:
我正在使用 ViewModel,因此 6 个不同的片段可以在 ViewModel 的函数中存储和检索数据。所以基本上,如果你有一个片段,其中有一个 EditText 并想在另一个片段中显示它的输入,这就是对我有用的方式:
- 使用 set 和 get 方法创建 ViewModel:
public class SharedViewModel extends ViewModel {
private MutableLiveData<String> mAnswer1 = new MutableLiveData<>();
private MutableLiveData<String> mAnswer2 = new MutableLiveData<>();
private MutableLiveData<String> mAnswer3 = new MutableLiveData<>();
public void setAnswer1 (String answer1){
mAnswer1.setValue(answer1);
}
public void setAnswer2 (String answer2){
mAnswer2.setValue(answer2);
}
public void setAnswer3 (String answer3){
mAnswer3.setValue(answer3);
}
public LiveData<String> getAnswer1(){
return mAnswer1;
}
public LiveData<String> getAnswer2(){
return mAnswer2;
}
public LiveData<String> getAnswer3(){
return mAnswer3;
}
}
- 在您有 EditText 并想使用其输入的片段中,您必须调用 ViewModel 的 set 方法。:
// This method gets the input of the EditText and "sends" it to the SharedViewModel where the next fragment can access it
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
EditText nameEditText = view.findViewById(R.id.edit_text_question_1);
// Add Text Watcher on name input text
nameEditText.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
viewModel.setAnswer1(charSequence.toString());
}
@Override public void afterTextChanged(Editable editable) {
}
});
}
在 onCreate 方法之前你必须调用这个:
public FragmentQuestion1() {
// Required empty public constructor
}
/**
* Create a new instance of this fragment
* @return A new instance of fragment FirstFragment.
*/
public static FragmentQuestion1 newInstance() {
return new FragmentQuestion1();
}
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init ViewModel
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel.class);
}
- 在要使用输入的片段中,只需调用 ViewModel 的 get 方法即可:
// Gets the answer from player 1 from the previous fragment and set the TextView to the answer
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tv_answer1 = view.findViewById(R.id.answer_player_1_text_view);
viewModel.getAnswer1().observe(requireActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
tv_answer1.setText(s);
}
});
}
就像在另一个片段中一样,你必须在 onCreate 方法之前调用以下内容:
/**
* Use this factory method to create a new instance of this fragment.
*
* @return A new instance of fragment SecondFragment.
*/
public static FragmentAnswer1 newInstance() {
return new FragmentAnswer1();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialise ViewModel here
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel.class);
}
我希望这会以某种方式帮助某些人,因为我花了很长时间才找到问题的正确答案。
所以基本上我想要实现的是将 EditText 的输入显示到另一个 Fragment 的 TextView 中。因此,用户回答一个问题并单击一个按钮,该按钮将他带到下一个片段,在 TextView 中应显示他的答案。由于我使用相同的方法有 3 个问题,因此我使用 ModelView 来实现此目的。由于我对编程比较陌生,所以我不知道这是否是我实现它的正确方法。非常感谢您的帮助!
这是我的视图模型:
public class SharedViewModel extends ViewModel {
private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();
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);
}
}
}
这是我第一个问题的第一个片段:
...
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(getViewLifecycleOwner(), new Observer<CharSequence>() {
@Override
public void onChanged(@Nullable CharSequence charSequence) {
mEditTextQuestion1.setText(charSequence);
}
});
}
这是我的答案概述片段,它显示在第一个问题片段之后,输入的答案应该替换 TextView 的默认值:
...
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(getViewLifecycleOwner(), new Observer<CharSequence>() {
@Override
public void onChanged(@Nullable CharSequence charSequence) {
tv_answer1.setText(charSequence);
}
});
}
}
Currently I get a NullPointerException at this line:
viewModel.getAnswer(1).observe(getViewLifecycleOwner(), new Observer<CharSequence>() {
在代码的这个特定部分:您没有为 get answer on key 1 设置任何值,您应该首先输入 MutableLiveData 键 "1":
viewModel.getAnswer(1)
首先你必须在 private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();
:
answers.put(1, new MutableLiveData<String>());
之后您可以通过代码访问可变的实时数据:viewModel.getAnswer(1)
public void setAnswer(int questionId, String answer) {
if (answers.get(questionId) != null) {
answers.get(questionId).setValue(answer);
}
}
LiveData 初始化错误。 您正在访问它而无需在 OnActivityCreated() 中进行内部初始化。 首先初始化你的 mutablelivedata。
我将举例说明如何使用 ViewModel 解决您的问题。
视图模型
public class ViewModel_RoutineStartConnection extends AndroidViewModel{
public ViewModel_RoutineStartConnection(
@NonNull Application application) {
super(application);
}
private MutableLiveData<String> sAnswer = new MutableLiveData<>();
public void setAnswer(String sAnswer){
this.sAnswer.post(sAnswer);
}
public LiveData<String> getsAnswer(){
return this.sAnswer;
}
}
使用 EditText 设置值的片段
public class Fragment_getAnswer extends Fragment {
private ViewModel_RoutineStartConnection myViewModle;
private EditText edittext;
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root =
inflater.inflate(R.layout.YOURLAYOUT, container, false);
edittext = root.findViewById(R.id.YOURID);
edittext.setOnEditorActionListener(listener);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myViewModle = ViewModelProviders.of(getActivity()).get(ViewModel_RoutineStartConnection.class);
}
public TextView.OnEditorActionListener listener = new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_DONE) {
myViewModle.setAnswer(edittext.getText.toString);
}
return false;
}
};
}
片段读取值
public class Fragment_setAnswer extends Fragment {
private ViewModel_RoutineStartConnection myViewModle;
private TextView textview;
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root =
inflater.inflate(R.layout.YOURLAYOUT, container, false);
textview= root.findViewById(R.id.YOURID);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
myViewModle = ViewModelProviders.of(getActivity()).get(ViewModel_RoutineStartConnection.class);
myViewModle.getsAnswer.observe(getViewLifecycleOwner(), obs_getsAnswer):
}
private Observer<String> obs_getsAnswer= new Observer<String>() {
@Override
public void onChanged(@Nullable String sAnswer) {
textview.setText(sAnswer);
}
};
}
要对所有答案使用此方法,我建议为每个答案添加一个 "id"。
所以当你设置 setAnswer("01" + answerText)
当您观察数据时,您可以使用:
switch(sAnswer.subString(0,3)){
case "01":
//set answer text for answer 1
break;
经过长时间的尝试,我找到了解决问题的正确方法:
我正在使用 ViewModel,因此 6 个不同的片段可以在 ViewModel 的函数中存储和检索数据。所以基本上,如果你有一个片段,其中有一个 EditText 并想在另一个片段中显示它的输入,这就是对我有用的方式:
- 使用 set 和 get 方法创建 ViewModel:
public class SharedViewModel extends ViewModel {
private MutableLiveData<String> mAnswer1 = new MutableLiveData<>();
private MutableLiveData<String> mAnswer2 = new MutableLiveData<>();
private MutableLiveData<String> mAnswer3 = new MutableLiveData<>();
public void setAnswer1 (String answer1){
mAnswer1.setValue(answer1);
}
public void setAnswer2 (String answer2){
mAnswer2.setValue(answer2);
}
public void setAnswer3 (String answer3){
mAnswer3.setValue(answer3);
}
public LiveData<String> getAnswer1(){
return mAnswer1;
}
public LiveData<String> getAnswer2(){
return mAnswer2;
}
public LiveData<String> getAnswer3(){
return mAnswer3;
}
}
- 在您有 EditText 并想使用其输入的片段中,您必须调用 ViewModel 的 set 方法。:
// This method gets the input of the EditText and "sends" it to the SharedViewModel where the next fragment can access it
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
EditText nameEditText = view.findViewById(R.id.edit_text_question_1);
// Add Text Watcher on name input text
nameEditText.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
viewModel.setAnswer1(charSequence.toString());
}
@Override public void afterTextChanged(Editable editable) {
}
});
}
在 onCreate 方法之前你必须调用这个:
public FragmentQuestion1() {
// Required empty public constructor
}
/**
* Create a new instance of this fragment
* @return A new instance of fragment FirstFragment.
*/
public static FragmentQuestion1 newInstance() {
return new FragmentQuestion1();
}
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init ViewModel
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel.class);
}
- 在要使用输入的片段中,只需调用 ViewModel 的 get 方法即可:
// Gets the answer from player 1 from the previous fragment and set the TextView to the answer
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tv_answer1 = view.findViewById(R.id.answer_player_1_text_view);
viewModel.getAnswer1().observe(requireActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
tv_answer1.setText(s);
}
});
}
就像在另一个片段中一样,你必须在 onCreate 方法之前调用以下内容:
/**
* Use this factory method to create a new instance of this fragment.
*
* @return A new instance of fragment SecondFragment.
*/
public static FragmentAnswer1 newInstance() {
return new FragmentAnswer1();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialise ViewModel here
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel.class);
}
我希望这会以某种方式帮助某些人,因为我花了很长时间才找到问题的正确答案。