我创建了一个全新的项目来演示我的问题.基本上,我的片段有两个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" />
我在log语句中设置了一个断点.当用户操作触发该断点时,堆栈跟踪将如下所示:
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)
但是当断断续续触发断点时,stracktrace看起来像这样:
onCheckedChanged:31,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,ZygoteInit (com.android.internal.os)
因此,我可以看到它是onRestoreInstanceState检查我的radioButtonSecond.但是我不知道如何预防.我正在考虑的事情:
>在onViewStateRestored中执行我的逻辑.但这不是一个干净的解决方案.
>每次需要打开片段时都要重新创建.但是,在创建新片段时,我的初始化阶段成本很高,我不应该这样做.
在我的真实项目中,此片段就像我的应用程序中的某项设置一样,它具有“取消”和“确定”按钮.因此,我希望片段每次打开时都处于默认状态,因为我认为,例如,用户可能配置了很多东西,但是按“取消”,则可以看到所有视图都处于默认状态状态,而不是已配置的状态(可能是这种想法导致了我的问题,这是一种良好的用户体验吗?)
因此,如何防止未经我允许的片段恢复其状态?
由于您希望每次用户离开后重新输入Fragment时都要检查第一个RadioButton,但(我想)不是当用户刚离开您的应用程序半小时然后又返回以继续他们中断的地方时,您应该使用取决于情况,以确保单选按钮具有正确的状态:
让我们介绍一个字段private boolean isFirstButtonChecked = true;.
保持OnCheckedChangeListener使用以下命令跟踪单选按钮的选中状态
isFirstButtonChecked = radioButtonFirst.isChecked();
除此之外,在OnClickListener中将布尔值设置为true
buttonReturn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isFirstButtonChecked = true;
getFragmentManager().beginTransaction().remove(WeirdFragment.this).commit();
}
});
现在,您可以将所需的状态保存在onSaveInstanceState()中:
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("FIRST_RB_STATE",isFirstButtonChecked);
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
isFirstButtonChecked = savedInstanceState == null
? true
: savedInstanceState.getBoolean("FIRST_RB_STATE");
radioButtonFirst.setChecked(isFirstButtonChecked);
}
我知道这意味着要添加很多代码.但是,由于我每次都不愿从头开始重新创建您的Fragment,所以我认为它不仅仅包含两个RadioButton.因此,让运行时为您工作而不是为它苦苦挣扎,使此方法比仅调用super.onViewStateRestored(null);更干净,更安全.在相应的方法中.