Как использовать ModelView для разных фрагментов, чтобы получить ввод EditText и установить TextView в его значение? - PullRequest
0 голосов
/ 22 сентября 2019

Итак, в основном я хочу добиться того, чтобы отображение ввода EditText в 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 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(getViewLifecycleOwner(), new Observer<CharSequence>() {
        @Override
        public void onChanged(@Nullable CharSequence charSequence) {
            mEditTextQuestion1.setText(charSequence);
        }
    });
}

И вот мой ответобзор Фрагмент, который отображается после первого вопроса «Фрагмент» и введенный ответ, должен заменить значение TextView по умолчанию:

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(getViewLifecycleOwner(), new Observer<CharSequence>() {
        @Override
        public void onChanged(@Nullable CharSequence charSequence) {
            tv_answer1.setText(charSequence);
        }
    });
}
}

В настоящее время я получаю исключение NullPointerException в этой строке:

viewModel.getAnswer(1).observe(getViewLifecycleOwner(), new Observer<CharSequence>() {

Вот LogCat:

java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.lifecycle.MutableLiveData.observe(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Observer)' on a null object reference
    at com.example.android.guessit.GameFlow.FragmentQuestion1.onActivityCreated(FragmentQuestion1.java:64)
    at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2619)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:904)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
    at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1696)
    at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:299)
    at androidx.fragment.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:259)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1244)
    at androidx.viewpager.widget.ViewPager.populate(ViewPager.java:1092)
    at androidx.viewpager.widget.ViewPager.onMeasure(ViewPager.java:1622)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7139)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:992)
    at android.view.View.measure(View.java:24966)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3301)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2028)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2330)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1888)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8511)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
    at android.view.Choreographer.doCallbacks(Choreographer.java:761)
    at android.view.Choreographer.doFrame(Choreographer.java:696)
    2019-09-22 11:36:47.984 31113-31113/com.example.android.guessit     E/AndroidRuntime:     at    android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.ja   va:935)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7050)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

Ответы [ 3 ]

1 голос
/ 22 сентября 2019

В этой конкретной части кода: у вас не установлено значение для получить ответ по ключу 1 , вы должны сначала поставить MutableLiveData для ключа "1":

viewModel.getAnswer(1)

Сначала вы должны ввести что-то в качестве ключа 1 в private HashMap<Integer, MutableLiveData<String>> answers = new HashMap<>();:

answers.put(1, new MutableLiveData<String>());

После этого вы можете получить доступ к изменяемым данным в реальном времени с помощью кода: viewModel.getAnswer(1)

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

Я приведу пример, как реализовать вашу проблему с ViewModel.

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;
0 голосов
/ 22 сентября 2019
public void setAnswer(int questionId, String answer) {
    if (answers.get(questionId) != null) {
        answers.get(questionId).setValue(answer);
    }
}

Ошибка при инициализации LiveData.Вы обращаетесь к нему без инициализации внутри в OnActivityCreated ().сначала запустите ваши изменяемые данные.

...