Я столкнулся с непоследовательными значениями возврата от Fragment.isRemoving()
, когда активность только что добавила фрагмент в задний стек. первый время, когда фрагмент временно уничтожен из-за изменения конфигурации, isRemoving()
возвращает значение true. Если фрагмент временно разрушен во второй раз, isRemoving()
возвращает false!
Мой код:
public class MainActivityFragment extends Fragment {
private static final String TAG = "MainActivityFragment";
private static final String LEVEL = "MainActivityFragment.LEVEL";
public MainActivityFragment() {
}
public static MainActivityFragment newInstance(int n) {
MainActivityFragment f = new MainActivityFragment();
f.setArguments(new Bundle());
f.getArguments().putInt(LEVEL, n);
return f;
}
private int getLevel() {
return (getArguments() == null) ? 0 : getArguments().getInt(LEVEL);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
Button button = (Button) rootView.findViewById(R.id.button);
button.setText(String.valueOf(getLevel()));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment, MainActivityFragment.newInstance(getLevel() + 1))
.addToBackStack(null)
.commit();
}
});
return rootView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, String.valueOf(getLevel()) + ": onCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, String.valueOf(getLevel()) + ": onDestroy");
Log.i(TAG, String.valueOf(getLevel()) + ": isChangingConfigurations() == " + getActivity().isChangingConfigurations());
Log.i(TAG, String.valueOf(getLevel()) + ": isRemoving() == " + isRemoving());
}
Журнал (строки, начинающиеся С#, являются моими комментариями):
# Start Activity
I/MainActivityFragment: 0: onCreate
# Click button in fragment 0 to add it to back stack and replace it with fragment 1
I/MainActivityFragment: 1: onCreate
# Rotate the device
I/MainActivityFragment: 0: onDestroy
I/MainActivityFragment: 0: isChangingConfigurations() == true
I/MainActivityFragment: 0: isRemoving() == true # ???????
I/MainActivityFragment: 1: onDestroy
I/MainActivityFragment: 1: isChangingConfigurations() == true
I/MainActivityFragment: 1: isRemoving() == false
I/MainActivityFragment: 0: onCreate
I/MainActivityFragment: 1: onCreate
# Rotate the device a second time
I/MainActivityFragment: 0: onDestroy
I/MainActivityFragment: 0: isChangingConfigurations() == true
I/MainActivityFragment: 0: isRemoving() == false # Correct result
I/MainActivityFragment: 1: onDestroy
I/MainActivityFragment: 1: isChangingConfigurations() == true
I/MainActivityFragment: 1: isRemoving() == false
I/MainActivityFragment: 0: onCreate
I/MainActivityFragment: 1: onCreate
# Click button in fragment 1 to add it to back stack and replace it with fragment 2
I/MainActivityFragment: 2: onCreate
# Rotate the device
I/MainActivityFragment: 0: onDestroy
I/MainActivityFragment: 0: isChangingConfigurations() == true
I/MainActivityFragment: 0: isRemoving() == false # Ok, correct
I/MainActivityFragment: 1: onDestroy
I/MainActivityFragment: 1: isChangingConfigurations() == true
I/MainActivityFragment: 1: isRemoving() == true # WHY????
I/MainActivityFragment: 2: onDestroy
I/MainActivityFragment: 2: isChangingConfigurations() == true
I/MainActivityFragment: 2: isRemoving() == false
I/MainActivityFragment: 0: onCreate
I/MainActivityFragment: 1: onCreate
I/MainActivityFragment: 2: onCreate
Является ли это ошибкой в Android или я понимаю это неправильно?
Обновление: Я добавил вызов в Fragment.dump() в onDestroy, и я получил следующие результаты:
Прежде чем фрагмент будет помещен в задний стек:
mFragmentId=#7f0c006b mContainerId=#7f0c006b mTag=null
mState=2 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0
mAdded=true mRemoving=false mResumed=false mFromLayout=false mInLayout=false
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
mRetainInstance=false mRetaining=false mUserVisibleHint=true
mFragmentManager=FragmentManager{336d670b in HostCallbacks{387c69e8}}
[email protected]69e8
mSavedViewState={[email protected]}
Child FragmentManager{2b6916a6 in null}}:
FragmentManager misc state:
mHost=null
mContainer=null
mCurState=0 mStateSaved=true mDestroyed=true
После того, как фрагмент помещается в задний стек и уничтожается в первый раз:
mFragmentId=#7f0c006b mContainerId=#7f0c006b mTag=null
mState=1 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1
mAdded=false mRemoving=true mResumed=false mFromLayout=false mInLayout=false
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
mRetainInstance=false mRetaining=false mUserVisibleHint=true
mFragmentManager=FragmentManager{34638ae1 in HostCallbacks{2db8e006}}
[email protected]e006
mSavedViewState={[email protected]}
Child FragmentManager{169d66c7 in null}}:
FragmentManager misc state:
mHost=null
mContainer=null
mCurState=0 mStateSaved=true mDestroyed=true
Разрушен второй раз:
mFragmentId=#7f0c006b mContainerId=#7f0c006b mTag=null
mState=1 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1
mAdded=false mRemoving=false mResumed=false mFromLayout=false mInLayout=false
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
mRetainInstance=false mRetaining=false mUserVisibleHint=true
mFragmentManager=FragmentManager{23beb2bc in HostCallbacks{c0f9245}}
[email protected]245
mSavedFragmentState=Bundle[{android:view_state={[email protected]}}]
mSavedViewState={[email protected]}
Различия между первым (а не задним стеком еще) и вторым (положить в задний стек):
- mState = 2 (
ACTIVITY_CREATED
) vs. mState = 1 (CREATED
) - mBackStackNesting = 0 против mBackStackNesting = 1
- mAdded = true vs. mAdded = false
- mRemoving = false vs. mRemoving = true (очевидно)
Различия между вторым (сначала уничтоженным) и третьим (вторым + временным отключением):
- mRemoving = true vs. mRemoving = false
- mSavedFragmentState = null vs mSavedFragmentState = Bundle [...]
- У Child FragmentManager нет дочернего элемента FragmentManager
Однако я не знаю, как интерпретировать эти результаты.
Я начинаю думать, что isRemoving
не то, что мне нужно (мне действительно нужно что-то эквивалентное Activity.isFinishing
, но для фрагментов. Мне нужно знать, что "этот фрагмент больше никогда не будет повторно использован", поэтому я может отменить фоновые задачи. Сейчас я использую isRemoving() && !getActivity().isChangingConfigurations()
, но я не уверен, что это правильное решение).