问题
I have an object Foo which can be configured using a fragment (FooFragment). The Foo class contains a static reference to FooFragment and the method public Fragment getConfigurationFragment(); this method assigns the current object to the FooFragment and returns it.
public class Foo{
private static FooFragment fooFragment = new FooFragment();
public Fragment getConfigurationFragment(){
fooFragment.setObject(this);
return fooFragment;
}
//various getters and setters
}
FooFragment is roughly as follows:
public class FooFragment extends Fragment{
private Foo f;
private EditText field1, field2, etc;
public void setObject(Foo f){
this.f = f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflate view
setupFieldListeners();
//return view object
}
@Override
private void onStart(){
super.onStart();
setupFields();
}
private void setupFields(){
field1.setText(f.getField1());
field2.setText(f.getField2());
//etc
}
private void setupListeners(){
field1.addTextChangedListener(new TextWatcher(){
@Override
public void afterTextChanged(Editable e){
f.setField1(e.getText().toString());
});
//Other empty necessary methods
field2.addTextChangedListener(new TextWatcher(){
//...
});
}
}
When I use the Fragment for the first time on object foo1, everything works great. The proper information is displayed and everything works.
When I use the Fragment for the second time on another object foo2, opening the Fragment causes all of the properties from foo1 (field1, field2, etc) to be written to the foo2. I believe that this is because when the Fragment is added again, the restoreViewState() method runs, which changes the values of the EditText fields to the values for foo1, causing the afterTextChanged() method to fire, and writing the values of foo1 into foo2.
I have tried the following to fix the problem:
-Creating a new FooFragment object whenever getConfigurationFragment() is called. This works, but I believe it's not optimal, as I understand that it's good to avoid needlessly creating objects on a mobile platform.
-Overriding onSaveInstanceState() in the Fragment and sending a null Bundle. This doesn't work as it doesn't look to be called when the Fragment is closed. It doesn't work.
-Placing the setupFields() call in OnStart(), OnResume(), OnCreateView(). None of these work as when the restoreViewState() runs, it clobbers foo2 object.
-Setting the Bundle to null in onCreate() and onCreateView(). Doesn't work.
What can I do to get the foo2 information to load into the reused Fragment?
I do not have the best understanding of the FragmentTransaction mechanism. Is it possible to somehow tell the FragmentManager to restore the View state?
Is the idea of reusing a configuration Fragment as I'm trying to do fundamentally flawed and to be avoided? If so why?
Is there some other magic that will cause this to work?
Thanks in advance for your time.
回答1:
I had a similar struggle with fragment view state restoration. One way to prevent it was to clear package-private mSavedViewState
field before restoreViewState()
is called:
package androidx.fragment.app;
import android.os.Bundle;
import android.view.View;
public class StatelessFragment extends Fragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mSavedViewState = null;
}
}
来源:https://stackoverflow.com/questions/28015159/preventing-fragment-restoreviewstate