按需加载片段UI

ᴛʜᴇ*_*ᴛᴇʟ 8 performance android android-fragments

问题:

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

我有BottomNavigationViewViewPager该负载4个片段-的每一个Fragment包含TabLayoutViewPager负载至少 2个片段。

可以想象,这是很多UI渲染(10多个片段)的-特别是当其中一些片段包含繁重的组件(如日历,条形图等)时。

当前提出的解决方案:

在需要片段时控制UI加载-因此,直到用户第一次访问该片段,才有理由加载它。

似乎肯定有可能,包括Play商店在内的许多应用都在这么做。请在此处查看示例

在上面的视频示例中-导航到选项卡后,正在加载UI组件。它甚至具有嵌入式的加载符号。

1)我试图弄清楚该怎么做-在什么时候我知道需要创建该片段UI还是已经创建了它?

2)另外,我将在其中启动UI创建过程的片段生命周期回调是什么?onResume()表示用户界面对用户可见,因此加载用户界面会很漫长和延迟。

希望这足够清楚。


编辑:
我已经在使用FragmentStatePagerAdapteras ViewPager适配器。我注意到super(fm)构造器中的方法现在已被弃用:

ViewPagerAdapter(FragmentManager fm) {
    super(fm); // this is deprecated
}
Run Code Online (Sandbox Code Playgroud)

所以我将其更改为:

ViewPagerAdapter(FragmentManager fm) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
Run Code Online (Sandbox Code Playgroud)

BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT:指示仅当前片段将处于Lifecycle.State.RESUMED状态。所有其他片段的上限为Lifecycle.State.STARTED。

这似乎是有用的作为onResume()Fragment时候才会被称为Fragment是对用户可见。可以通过某种方式使用此指示加载UI吗?

Far*_*rid 1

您的应用程序在启动时加载多个片段的原因很可能是您一次初始化它们。相反,您可以在需要时初始化它们。然后使用show\ hideto attach\ detachfrom window 而不重新扩展整个布局。

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

根据您的情况show()/比/hide更好,因为正如您所说,当您想要显示它们时,您不想重新膨胀片段add()replace

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如ViewPager您从您所提到的示例中看到的那样;PlayStore 正在使用setOffscreenPageLimit. 这将让您选择应保持多少个Views 处于活动状态,否则将被销毁并从一开始就通过 Fragment 的所有生命周期事件创建(如果视图是 Fragment)。在 PlayStore 应用程序的情况下,这可能是 4-5 这就是为什么当您重新选择“编辑器的选择”选项卡时它再次开始加载的原因。如果执行以下操作,则仅选定的相邻(右侧之一)片段将处于活动状态,屏幕外的其他片段将被销毁。

public class FragmentOne extends Fragment{ 
    ViewPager viewPager;
    @Override
    public void onCreateView(){
        viewPager = .... // Initialize
        viewpAger.setOffscreenPageLimit(1); // This will keep only 2 Fragments "alive"
    }
}
Run Code Online (Sandbox Code Playgroud)

回答两个问题

如果您使用show/hide您将不需要知道何时膨胀您的视图。它将自动处理并且不会延迟,因为它只是attaching/detaching视图不会膨胀。