问题描述
crash,小同学不知道如何修复,通过wx发我帮忙看看. 通过这个demo,帮他演示下修复过程和利用Git.
Process: com.eno.enotest, PID: 20975
java.lang.IllegalStateException: Fragment no longer exists for key f0: unique id e1e49495-203d-445f-941a-53f0d4256e05
at androidx.fragment.app.FragmentManagerImpl.getFragment(FragmentManagerImpl.java:365)
at androidx.fragment.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:309)
at androidx.viewpager.widget.ViewPager.onRestoreInstanceState(ViewPager.java:1461)
at android.view.View.dispatchRestoreInstanceState(View.java:19830)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3858)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3864)
at android.view.View.restoreHierarchyState(View.java:19808)
at androidx.fragment.app.Fragment.restoreViewState(Fragment.java:548)
解决办法(2种)
- 在HomeFragment的89行后添加一个函数
@Nullable
@Override
public Parcelable saveState() {
return null;
}

- 把HomeFragment的FragmentStatePagerAdapter修改成FragmentPagerAdapter

解决思路
Fragment嵌套的时候出现了状态恢复错误.

- 一般这种问题考虑怎么让解决异常代码不被执行即可.
( at androidx.fragment.app.FragmentManagerImpl.getFragment(FragmentManagerImpl.java:365) SDK29 中
@Nullable
public Fragment getFragment(Bundle bundle, String key) {
String who = bundle.getString(key);
if (who == null) {
return null;
}
Fragment f = mActive.get(who);
if (f == null) {
throwException(new IllegalStateException("Fragment no longer exists for key "
+ key + ": unique id " + who));
}
return f;
}
在 if (f == null) 的后面发生了异常,看函数在 if (who == null) 的时候会直接跳出去,问题转化为怎么让who为null.
- 往上层调用栈看
at androidx.fragment.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:309) 中
@Override
public void restoreState(@Nullable Parcelable state, @Nullable ClassLoader loader) {
if (state != null) {
Bundle bundle = (Bundle)state;
bundle.setClassLoader(loader);
Parcelable[] fss = bundle.getParcelableArray("states");
mSavedState.clear();
mFragments.clear();
if (fss != null) {
for (int i=0; i<fss.length; i++) {
mSavedState.add((Fragment.SavedState)fss[i]);
}
}
Iterable<String> keys = bundle.keySet();
for (String key: keys) {
if (key.startsWith("f")) {
int index = Integer.parseInt(key.substring(1));
Fragment f = mFragmentManager.getFragment(bundle, key);
if (f != null) {
while (mFragments.size() <= index) {
mFragments.add(null);
}
f.setMenuVisibility(false);
mFragments.set(index, f);
} else {
Log.w(TAG, "Bad fragment at key " + key);
}
}
}
}
}
如何让 Fragment f = mFragmentManager.getFragment(bundle, key);中的bundle中不包含fragment.分析函数发现bundle的赋值是在
Parcelable[] fss = bundle.getParcelableArray("states");中问题也就转化成了怎么让states的Parcelable中不包含值.
- 在FragmentStatePagerAdapter类中搜索关键字states,发现函数
saveState()

结论
- 给新同学示范演示下如何通过源码追踪问题.
- 利用Git,交流表达.