如何在不同的 Fragment 上使用 ModelView 来获取 EditText 的输入并将 TextView 设置为其值?
Posted
技术标签:
【中文标题】如何在不同的 Fragment 上使用 ModelView 来获取 EditText 的输入并将 TextView 设置为其值?【英文标题】:How to use ModelView on different Fragments to get the input of an EditText and set a TextView to its value? 【发布时间】:2020-01-22 16:52:57 【问题描述】:所以基本上我想要实现的是将 EditText 的输入显示到另一个 Fragment 的 TextView 中。因此,用户回答一个问题并单击一个按钮,该按钮将他带到下一个片段,在 TextView 中应该显示他的答案。由于我使用相同的方法有 3 个问题,因此我使用 ModelView 来实现这一点。由于我对编程比较陌生,我不知道这是否是我实现它的正确方法。非常感谢您的帮助!
这是我的 ViewModel:
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>()
【问题讨论】:
请提供LogCat 尝试将onActivityCreated的代码移到fragment的onCreate中 将代码移动到onCreate后仍然显示相同的错误 我需要在 ViewModel 中初始化地图但我不知道该怎么做 【参考方案1】:在代码的这个特定部分:您没有为 get answer on key 1 设置任何值,您应该首先将 MutableLiveData 设置为 key " 1":
viewModel.getAnswer(1)
首先,您必须在private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();
中输入一些内容作为key 1:
answers.put(1, new MutableLiveData<String>());
之后您可以通过代码访问可变的实时数据:viewModel.getAnswer(1)
【讨论】:
我添加了类似这样的代码 private HashMappublic void setAnswer(int questionId, String answer)
if (answers.get(questionId) != null)
answers.get(questionId).setValue(answer);
LiveData 初始化错误。 您无需在 OnActivityCreated() 内部进行初始化即可访问它。 首先初始化你的 mutablelivedata。
【讨论】:
【参考方案3】:我将举一个例子,说明如何解决 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;
【讨论】:
【参考方案4】:经过长时间的尝试,我找到了解决问题的正确方法:
我正在使用 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);
我希望这能以某种方式帮助某人,因为我为找到问题的正确答案而苦苦挣扎了很长时间。
【讨论】:
以上是关于如何在不同的 Fragment 上使用 ModelView 来获取 EditText 的输入并将 TextView 设置为其值?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 List<Model> 从 Activity 传递到 Fragment
如何在同一页面上的 Fragment 内创建具有 3 个 Fragment 的 ViewPager?