android - 按需加载 Fragment UI

标签 android performance android-fragments

问题:

我目前遇到一个问题,即我的应用程序在首次打开时尝试加载太多 fragment 。

我有 BottomNavigationViewViewPager加载 4 个 fragment - Fragment 中的每个 fragment 包含 TabLayoutViewPager加载 至少 还有2个 fragment 。

可以想象,这是很多 UI 渲染(10 多个 fragment )——尤其是当其中一些 fragment 包含重组件时,例如日历、条形图等。

目前建议的解决方案:

在需要 fragment 时控制 UI 加载 - 因此在用户第一次访问该 fragment 之前,没有理由加载它。

看起来这绝对是可能的,因为包括 Play 商店在内的许多应用程序都在这样做。请看示例 here

在上面的视频示例中 - 在完成导航到选项卡后加载 UI 组件。它甚至有一个嵌入的加载符号。

1)我试图弄清楚如何做到这一点 - 在什么时候我会知道这个 fragment UI 需要创建而不是它已经创建?

2) 另外,我将启动 UI 创建过程的 fragment 生命周期回调是什么? onResume()表示 UI 对用户可见,因此加载 UI 会有延迟和延迟。

希望这足够清楚。

编辑:
我已经在使用 FragmentStatePagerAdapterViewPager适配器。我注意到 super(fm)现在不推荐使用构造函数中的方法:

ViewPagerAdapter(FragmentManager fm) {
    super(fm); // this is deprecated
}

所以我将其更改为:
ViewPagerAdapter(FragmentManager fm) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT :表示只有当前 fragment 将处于 Lifecycle.State.RESUMED 状态。所有其他 fragment 的上限为 Lifecycle.State.STARTED。

这似乎很有用 onResume()Fragment只会在 Fragment 时调用对用户可见。我可以使用这个指示以某种方式加载 UI 吗?

最佳答案

您的应用程序在启动时加载多个 fragment 的原因很可能是您一次将它们全部初始化。相反,您可以在需要时初始化它们。然后使用 show\hideattach\detach从窗口无需重新充气整个布局。

简单解释:一旦用户点击 BottomNavigationView,您将创建您的 Fragment的项。在单击的项目上,您将检查 Fragment 是否未创建且未添加,然后创建并添加。如果已经创建,则使用 show()显示已可用 fragment 的方法并使用 hide()隐藏 BottomNavigationView 的所有其他 fragment .

根据您的情况show()/hide优于add()/replace因为正如你所说,当你想展示它们时,你不想重新膨胀 fragment

public class MainActivity extends AppCompatActivity{ 
    FragmentOne frg1;
    FragmentTwo frg2;

    @Override
    public boolean onNavigationItemSelected(MenuItem item){
        switch(item.getId()){
            case R.id.fragment_one:
                if (frg2 != null && frg2.isAdded(){
                    fragmentManager.beginTransaction().hide(frg2).commit();
                }
                if(frg1 != null && !frg1.isAdded){
                    frg1 = new FragmenOne();
                    fragmentManager.beginTransaction().add(R.id.container, frg1).commit();
                }else if (frg1 != null && frg1.isAdded) {
                    fragmentManager.beginTransaction().show(frg1).commit();
                }
                return true;
            case R.id.fragment_two:
            // Reverse of what you did for FragmentOne
            return true;
        }
    }
}

并为您的ViewPager从您所指的示例中可以看出; PlayStore 正在使用 setOffscreenPageLimit .这将让您选择多少 View s 应该保持 Activity 状态,否则将从开始通过 Fragment 的所有生命周期事件(如果 View 是 Fragment)被销毁和创建。在 PlayStore 应用程序的情况下,这可能是 4-5,这就是为什么当您重新选择“编辑器的选择”选项卡时它再次开始加载的原因。如果您执行以下操作,则只有选定的和相邻的(右侧的一个) fragment 会活着,屏幕外的其他 fragment 将被销毁。
public class FragmentOne extends Fragment{ 
    ViewPager viewPager;
    @Override
    public void onCreateView(){
        viewPager = .... // Initialize
        viewpAger.setOffscreenPageLimit(1); // This will keep only 2 Fragments "alive"
    }
}

回答这两个问题

如果您使用 show/hide您无需知道何时放大您的 View 。它将被自动处理并且不会滞后,因为它只是 attaching/detaching View 没有膨胀。

关于android - 按需加载 Fragment UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57882630/

相关文章:

ruby - 查看数组中的所有元素是否具有特定值的最快方法

c - 为什么 glibc 的 sscanf 在 Linux 上比 fscanf 慢很多?

android - fragment 和 fragment Activity 天生就比 Activity 快吗?

java - 从 Activity 中更新 fragment ListView

android - RecyclerView 网格布局管理器 : change column width

android - 及时获取加速度计值

java - 无法实例化服务java.lang.NullPointerException

android - mac os 中 android studio 中正确的 Assets 文件夹路径是什么

mysql - 性能:mysql 和连接

android - 如何从 fragment 实现本地化?