Я создал совершенно новый проект, чтобы продемонстрировать свою проблему. По сути, мой фрагмент имеет два RadioButton
. Когда onCreateView, я всегда использую radioButtonFirst.setChecked(true);
. Но если я проверяю radioButtonSecond
, а затем нажимаю кнопку «Назад», при следующем открытии он автоматически проверяет radioButtonSecond
. Такое поведение нарушает мою логику.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private WeirdFragment weirdFragment;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weirdFragment = new WeirdFragment();
fragmentManager = getSupportFragmentManager();
}
public void openFragment(View v){
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, weirdFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
WeirdFragment.java
public class WeirdFragment extends Fragment {
private RadioButton radioButtonFirst;
private RadioButton radioButtonSecond;
private Button buttonReturn;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_weird, container, false);
radioButtonFirst = view.findViewById(R.id.radio_button_first);
radioButtonSecond = view.findViewById(R.id.radio_button_second);
buttonReturn = view.findViewById(R.id.button_return);
radioButtonFirst.setChecked(true);
// I decide to set a listener right here, to see what happened to my radio button. So this listener will be removed in my real project.
radioButtonSecond.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.v("weird", "i got here");
}
});
buttonReturn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getFragmentManager().beginTransaction().remove(WeirdFragment.this).commit();
}
});
return view;
}
}
activity_main.xml
<Button
android:id="@+id/button_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="openFragment"
android:text="Open"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/button_open" />
fragment_weird.xml
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:id="@+id/radio_button_first"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:text="First" />
<RadioButton
android:id="@+id/radio_button_second"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Second" />
</RadioGroup>
<Button
android:id="@+id/button_return"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Return"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
Я установил точку останова в операторе журнала. Эта точка останова, когда она запускается действием пользователя, трассировка стека будет выглядеть так:
onCheckedChanged:31, WeirdFragment$1 (com.peanut.myweirdradiobutton)
setChecked:154, CompoundButton (android.widget)
toggle:113, CompoundButton (android.widget)
toggle:78, RadioButton (android.widget)
performClick:118, CompoundButton (android.widget)
run:19866, View$PerformClick (android.view)
handleCallback:739, Handler (android.os)
dispatchMessage:95, Handler (android.os)
loop:135, Looper (android.os)
main:5254, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
invoke:372, Method (java.lang.reflect)
run:903, ZygoteInit$MethodAndArgsCaller (com.android.internal.os)
main:698, ZygoteInit (com.android.internal.os)
Но когда эта точка останова запускается из ниоткуда, трассировка выглядит следующим образом:
onCheckedChanged:31, WeirdFragment$1 (com.peanut.myweirdradiobutton)
setChecked:154, CompoundButton (android.widget)
onRestoreInstanceState:522, CompoundButton (android.widget)
dispatchRestoreInstanceState:13740, View (android.view)
dispatchRestoreInstanceState:2893, ViewGroup (android.view)
dispatchRestoreInstanceState:2893, ViewGroup (android.view)
restoreHierarchyState:13718, View (android.view)
restoreViewState:494, Fragment (android.support.v4.app)
moveToState:1486, FragmentManagerImpl (android.support.v4.app)
moveFragmentToExpectedState:1784, FragmentManagerImpl (android.support.v4.app)
moveToState:1852, FragmentManagerImpl (android.support.v4.app)
executeOps:802, BackStackRecord (android.support.v4.app)
executeOps:2625, FragmentManagerImpl (android.support.v4.app)
executeOpsTogether:2411, FragmentManagerImpl (android.support.v4.app)
removeRedundantOperationsAndExecute:2366, FragmentManagerImpl (android.support.v4.app)
execPendingActions:2273, FragmentManagerImpl (android.support.v4.app)
run:733, FragmentManagerImpl$1 (android.support.v4.app)
handleCallback:739, Handler (android.os)
dispatchMessage:95, Handler (android.os)
loop:135, Looper (android.os)
main:5254, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
invoke:372, Method (java.lang.reflect)
run:903, ZygoteInit$MethodAndArgsCaller (com.android.internal.os)
main:698, ZygoteInit (com.android.internal.os)
Итак, я вижу, что onRestoreInstanceState проверяет мой radioButtonSecond
. Но я не знаю, как это предотвратить. Вещи, которые я рассматриваю:
- Выполнение моей логики в onViewStateRestored. Но это скорее не чистое решение.
- Повторно создавайте мой фрагмент каждый раз, когда мне нужно его открыть. Но моя фаза инициализации при создании нового фрагмента дорогая, я не должен этого делать.
В моем реальном проекте этот фрагмент похож на настройку чего-либо в моем приложении, он имеет кнопку Отмена и кнопку ОК. Итак, я хочу, чтобы фрагмент находился в своем состоянии по умолчанию каждый раз, когда он открывается, потому что я думаю, что, например, пользователь может настроить много разных вещей, но затем нажать кнопку «Отмена», тогда разумно будет увидеть, что все представления имеют свои значения по умолчанию. состояния, а не настроенные (может быть, эта мысль вызывает у меня проблему, это хороший пользовательский опыт?)
Итак, как помешать моему фрагменту восстановить свое состояние без моего разрешения?