У меня есть приложение, состоящее из (помимо прочего) одного занятия и одного фрагмента. В Activity som данные отображаются с помощью TextViews, а во Fragment пользователь может вводить некоторые данные с помощью EditText-views. У меня есть метод, который берет данные как из действия, так и из фрагмента, выполняет некоторые вычисления и, наконец, отображает результат как во фрагменте, так и в действии. Этот метод в настоящее время работает, когда я вызываю, если после редактирования текста в любом из EditText-представлений во фрагменте. Однако я также хочу вызывать его каждый раз, когда обновляю данные в Activity, но когда я пытаюсь это сделать, я не могу извлечь данные EditText, потому что они возвращают ноль.
Итак, мой вопрос: что является хорошей практикой или «правильным способом» делать, когда имеешь дело с методами, которые должны быть получены как из Действия, так и из Фрагмента? Я был бы очень признателен, если бы кто-нибудь смог привести меня на правильный путь.
Я прочитал официальную документацию по фрагментам , и там была упомянута ViewModel. Но это не кажется подходящим для моего приложения, так как я хочу, чтобы Activity была вовлечена. Нужно ли мне использовать это или я могу пройти мою основную деятельность? Я также читал об интерфейсах, но не уверен, какой из них лучше всего подойдет для моего проекта. В настоящее время я использую интерфейсы, но я не уверен, правильно ли я это делаю.
Я также посмотрел это видео и прочитал следующие вопросы:
Ответ "Боже мой" на этот вопрос был полезен, но я все еще не уверен, что лучше всего сделать в моем случае, так как у меня есть фрагмент, где пользователь может вводить данные, и тот же фрагмент должен также просматривать данные в результате этого ввода. (Может быть, моей первой ошибкой является создание такого приложения?)
Я предоставляю код на случай, если он будет полезен.
public class AccuracyFragment extends Fragment {
EditText editTextLevel, editTextAccuracy;
private OnFragmentInteractionListener mListener;
public AccuracyFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_accuracy, container, false);
editTextAccuracy = view.findViewById(R.id.text_accuracy_character);
editTextLevel = view.findViewById(R.id.text_level_character);
TextWatcher watcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//Doing nothing
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//Doing nothing
}
@Override
public void afterTextChanged(Editable editable) {
updateFragment(Float.valueOf(editTextLevel.getText().toString()), Float.valueOf(editTextAccuracy.getText().toString()));
}
};
editTextLevel.addTextChangedListener(watcher);
editTextAccuracy.addTextChangedListener(watcher);
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null; //I don’t know what this does
}
@Override
public void onResume() {
super.onResume();
// updateFragment(); //Should I have this?
}
public interface OnFragmentInteractionListener {
String[] onAccuracyFragmentInputChanged(float levelFromFragment, float accuracyFromFragment); }
public void updateFragment(float level, float accuracy) {
//Complicated method doing things with editTextLevel and editTextAccuracy. However, it doesn’t work when this method is called from outside AccuracyFragment – EditTexts are null
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onStop() {
super.onStop();
}
}
public class MainActivity extends AppCompatActivity implements AccuracyFragment.OnFragmentInteractionListener, AdapterView.OnItemSelectedListener {
AccuracyFragment accuracyFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_new);
selectedID = null;
textView1 = (TextView) findViewById(R.id.text_1);
textView2 = (TextView) findViewById(R.id.text_2);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.fragment_container) != null) {
// However, if we're being restored from a previous state, then we don't need to do anything and should return or else we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
accuracyFragment = new AccuracyFragment();
}
}
//This is the core method which takes the value from two EditTexts in the Fragment, and two TextViews in the MainActivity
private String[] getRequiredAccuracy(float firstValueFromActivity, float secondValueFromActivity, float firstValueFromFragment, float secondValueFromFragment) {
//This methods uses parameters from the Activity, and two from the Fragment, and is intended to be called from both the Activity and from the Fragment itself
String returnValues[] = {s, q, r, c}; //This method is too complex to show, but it will end up outputting some values
return returnValues;
}
public void methodCalledUponClick(View view) {
//After showing a Dialog with some choices, I intend to call the method from fragment:
accuracyFragment.updateFragment();
}
@Override
public String[] onAccuracyFragmentInputChanged(float levelFromFragment, float accuracyFromFragment) {
String returnValues[] = {"0", "0", "0"};
if (selectedID != null) {
if (textView1.length() == 0 || textView2.length() == 0) {
//Do nothing if any of these are empty
} else {
returnValues = getRequiredAccuracy(Float.valueOf(textView1.getText().toString()), Float.valueOf(textView2.getText().toString()), levelFromFragment, accuracyFromFragment);
}
}
return returnValues;
}
}
}