FragmentTabHost 每次都重新创建 View 分析与解决(最佳方案)

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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值