FragmentTabHost 每次都重新创建 View 分析与解决
1. 概述
1.1 问题描述
- 使用 FragmentTabHost 做主页 tab,但是发现每次都要重新创建 view, 经过分析发现是由于 FragmentTabHost 使用 attach()/detach() 来完成 Fragment 的切换, 而不是 show()/hide(); 有网友通过自己做 View 的缓存, 以实现 View 的复用, 但不是从根本上解决问题, 另外每个 Fragment 都要处理一遍,而我们是四端合一,有 16 个…
1.2 解决思路
- 既然问题在于使用了 attach()/detach(),换成 show()/hide() 不就行了 ?
2. 代码分析与实现
2.1 代码分析
- FragmentTabHost 使用 doTabChanged() 函数完成 Fragment 切换,我们看这个函数就行了,最后其实只要把 attach()/detach() 改成 show()/hide() 就好了
private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {
TabInfo newTab = null;
for (int i=0; i<mTabs.size(); i++) {
TabInfo tab = mTabs.get(i);
if (tab.tag.equals(tabId)) {
newTab = tab;
}
}
if (newTab == null) {
throw new IllegalStateException("No tab known for tag " + tabId);
}
if (mLastTab != newTab) {
if (ft == null) {
ft = mFragmentManager.beginTransaction();
}
if (mLastTab != null) {
if (mLastTab.fragment != null) {
ft.detach(mLastTab.fragment); // 隐藏并销毁 view, 修改为调用 hide() 即可
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mContext,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
ft.attach(newTab.fragment); // 显示, 修改为调用 show() 即可
}
}
mLastTab = newTab;
}
return ft;
}
}
2.2 实现
1. 复制一份 FragmentTabHost 的源码改名为 FastFragmentTabHost,我从这里找的https://www.androidos.net.cn/android/8.0.0_r4/xref/frameworks/support/v13/java/android/support/v13/app/FragmentTabHost.java
2. 修改 doTabChanged() 函数成下面的样子, 然后替换布局文件中的类名和代码的类名为 FastFragmentTabHost 即可
private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {
TabInfo newTab = null;
for (int i=0; i<mTabs.size(); i++) {
TabInfo tab = mTabs.get(i);
if (tab.tag.equals(tabId)) {
newTab = tab;
}
}
if (newTab == null) {
throw new IllegalStateException("No tab known for tag " + tabId);
}
if (mLastTab != newTab) {
if (ft == null) {
ft = mFragmentManager.beginTransaction();
}
if (mLastTab != null) {
if (mLastTab.fragment != null) {
// ft.detach(mLastTab.fragment);
ft.hide(mLastTab.fragment); // edited by Ken
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mContext,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
// ft.attach(newTab.fragment);
ft.show(newTab.fragment); // edited by Ken
}
}
mLastTab = newTab;
}
return ft;
}