如未特别阐明,本文中的知识点适用于 Activity 重建的时分,即:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) // 略........ if (savedInstanceState != null) { // 本文评论的状况 } else { // 非本文评论的状况 } // 略........ }
复用的优点:
FragmentManager.findFragmentByTag(String tag)
throw new IllegalStateException("Fragment already added: " + fragment)
### 理由二:次序不可控 下面的这段代码我信任咱们都很了解,就算自己没有写过也看他人写过
throw new ClassCastException("Cannot cast android.arch.lifecycle.HolderFragment to MainFragment")
从 ```ViewModel```相关源码那里能够知道```FragmentManager.getFragments()``` 中包括了其他的Fragment,而这些Fragment的方位往往是不固定,以ViewModel为例,HolderFragment的方位是由初始化的机遇决议的。
也便是说你调整了一下 ViewModel 初始化的调用次序或许在Kotlin项目中将 ```lateinit``` 改成了 ```by lazy``` 都或许会发作这样的Crash!就 ```lateinit``` 改成 ```by lazy``` 这条便是我前不久在做项目时实在遇到的。 ### 理由三:26.x.y 版别中行为发作改变 在 版别25 中 Activity 是新建的状况下 回来的是 ```null``` ,在版别26中回来的是 ```Collections.EmptyList[ROOM]()(https://developer.android.google.cn/topic/libraries/architecture/room) 然后有几个界面溃散了! 经过扫除发现而问题就出鄙人面的这段代码中。
}else{
mFragments.addAll(fm.getFragments())
用法示例:
private MainFragment mainFragment; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) {
mainFragment = (MainFragment) getSupportFragmentManager() // 这个ID和下面增加 fragment 时指定的 id 要共同 .findFragmentById(android.R.id.content);
} else {
mainFragment = new MainFragment();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, mainFragment)
.commit();
}
}
办法签名:
public abstract Fragment findFragmentByTag(String tag);
上面便是一个很简单的用 TAG 来获取Fragment 的比如,这儿需求留意的便是 tag 参数是咱们在进行 add 或 replace 操作的时分指定的。
依据 TAG 查找 Fragment
【要点】依据 Key 查找 Fragment,这个适宜与 ViewPager 合作
该办法比较适宜 ViewGroup 和 Fragment 是一对一的状况下运用,当不满足该条件时能够运用后边介绍的 findFragmentByTag 办法。
当 一个 ViewGroup 中 有多个 Fragment 时该办法会回来最终增加到该 ViewGroup 的 Fragment。
tag 是能够重复的,因为该参数的之仅仅 Fragment 的一个成员变量,仅仅咱们无法拜访(拜访权限 default)。
该办法总是回来 FragmentManager 中和该 tag 共同的最终一个 Fragment。也便是说假如有多个 Fragment 目标运用了同一个 tag 那么最终一个被增加的会被回来,所以不要为不同的 Fragment 目标指定相同的 tag。
不要为同一个 Fragment 实例目标指定在不同的操作中指定不同的 tag,否则会抛出反常,当然这种状况一般是发作在重复增加的状况下
正确的处理姿态演示:
private MainFragment mainFragment; private SecondaryFragment secondaryFragment; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) {
mainFragment = (MainFragment) fm.getFragment(savedInstanceState, MainFragment.TAG);
secondaryFragment = (SecondaryFragment) fm.getFragment(savedInstanceState, SecondaryFragment.TAG);
} if (mainFragment == null) {
mainFragment = new MainFragment();
} if(secondaryFragment == null){
secondaryFragment = new SecondaryFragment()
} // ViewPager 的相关操作 } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mainFragment.isAdded()) {
fm.putFragment(outState, MainFragment.TAG, mainFragment);
} if (secondaryFragment.isAdded()) {
fm.putFragment(outState, SecondaryFragment.TAG, secondaryFragment);
}
}
原理解析:
上图仅仅给出了咱们现已知道的,不知道的 Fragment 没有表示出来,但不代表不存在
以 图中 Fragment A 为例,其他的同理
热门源码