【问题标题】:Android Navigation Component has lag when navigating through NavigationDrawerAndroid Navigation 组件在通过 NavigationDrawer 导航时有延迟
【发布时间】:2019-07-11 13:40:56
【问题描述】:

我正在将我的应用程序更新为导航架构组件,我发现它有一个延迟替换片段,该片段在 N​​avigationDrawer 中可见,并且无法顺利关闭。

到目前为止,我一直在遵循这种方法:

https://vikrammnit.wordpress.com/2016/03/28/facing-navigation-drawer-item-onclick-lag/

所以我在onDrawerClosed 中导航而不是在onNavigationItemSelected 中导航以避免故障。

这是一个非常普遍的问题,但它又回来了。使用导航组件,它又是滞后的,我看不到在onDrawerClosed 中实现它的方法。

这些是导航组件之前的一些旧答案

Navigation Drawer lag on Android

DrawerLayout's item click - When is the right time to replace fragment?

非常感谢。

【问题讨论】:

  • 不幸的是,我遇到了同样的问题。我想出的唯一解决方法是让 Fragment 在加载其内容之前稍等片刻,但这远非理想。我希望有更好的方法来解决这个问题......
  • 可以公开代码和xml吗?
  • 我不知道 2019 年的情况如何,但是使用 Navigation 版本 2.4.1 可以覆盖 onDrawerClosed 并使用 NavController 类和 .navigate(..) 方法放置片段导航逻辑。据我所知。

标签: android navigation-drawer android-architecture-navigation navigationview


【解决方案1】:

我在写这个答案时正在解决这个问题。经过一些测试,我得出结论,我在创建片段后立即在片段中执行的代码(例如初始化 RecyclerView 适配器并用数据填充它,或配置 UI)导致抽屉滞后,因为这一切同时发生。

现在我得到的最好的想法类似于一些依赖onDrawerClosed 的旧解决方案。我们延迟片段中代码的执行,直到抽屉关闭。在抽屉关闭之前,片段的布局将变得可见,因此它仍然看起来快速且响应迅速。

请注意,我也在使用导航组件。

首先,我们将创建一个接口并实现它的片段。

interface StartFragmentListener {
    fun configureFragment()
}

在活动设置 DrawerListener 中像:

private fun configureDrawerStateListener(){
    psMainNavDrawerLayout.addDrawerListener(object: DrawerLayout.DrawerListener{
        override fun onDrawerStateChanged(newState: Int) {}
        override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
        override fun onDrawerOpened(drawerView: View) {}

        override fun onDrawerClosed(drawerView: View) {
            notifyDrawerClosed()
        }

    })
}

通知片段抽屉已关闭,它可以执行导致延迟的操作:

private fun notifyDrawerClosed(){
    val currentFragment =
            supportFragmentManager.findFragmentById(R.id.psMainNavHostFragment)
                    ?.childFragmentManager?.primaryNavigationFragment

    if(currentFragment is StartFragmentListenr && currentFragment != null)
        currentFragment.configureFragment()

}

如果您没有从抽屉导航到片段(例如按下后退按钮),您还需要通知片段执行它的操作。我们将实现 FragmentLifecycleCallbacksListener:

private fun setupFragmentLifecycleCallbacksListener(){
    supportFragmentManager.findFragmentById(R.id.psMainNavHostFragment)
            ?.childFragmentManager?.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() {

        override fun onFragmentActivityCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?) {
            super.onFragmentActivityCreated(fm, f, savedInstanceState)

            if (!psMainNavDrawerLayout.isDrawerOpen(GravityCompat.START)) {
                if (f is StartFragmentListener)
                    f.configureFragment()
            }

        }
    }, true)
}

在片段中:

class MyFragment: Fragment(), MyActivity.StartFragmentListener {
    private var shouldConfigureUI = true
    ...

    override fun onDetach() {
        super.onDetach()
        shouldConfigureUI = true
    }

    override fun configureFragment() {
        if(shouldConfigureUI){
            shouldConfigureUI = false
            //do your things here, like configuring UI, getting data from VM etc...
            configureUI()
        }
    }
} 

可以使用共享视图模型实现类似的解决方案。

【讨论】:

  • 如果还可以从抽屉导航到外面的片段呢?我必须“手动”打电话给configureFragment(),对吗?
  • 不,这个解决方案会处理它。 BackStackListener 将在宿主 Fragment 中注册每个 Fragment 更改,但如果在 Fragment 更改时关闭了抽屉,它只会调用 configureFragment() - 表明我们导航到抽屉外的该 Fragment。
  • 啊!你说得对。太棒了:) 好主意。我今天测试一下。
  • 我已经测试了你的解决方案,伙计,这对性能有很大的改进,谢谢!至于潜在的错误,一个标志可能会解决问题,但我也不确定它是否真的会发生。
  • @Mauker 它必须完成,我错过了。我马上更新,谢谢。
【解决方案2】:

避免更改Fragment / Activity onNavigationItemSelected-Android时造成的滞后

导航抽屉是应用程序中最常用的选项,当我们有超过五个选项时,我们会进入导航菜单。

我在许多应用程序中看到,当我们从导航菜单中更改选项时,我们观察到它会滞后,StackOverflow 上的一些人建议使用 Handler,如下面的代码:

private void openDrawerActivity(final Class className) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                ProjectUtils.genericIntent(NewDrawer.this, className, null, false);
            }
        }, 200);
    }

但是在上面的代码中,它仍然不流畅&我想为什么我们添加处理程序可能是经过这么多研发后还有另一种解决方案,我发现我们需要在抽屉运行时更改片段/活动接近。让我们看看实现。

有关解决方案的更多详细信息,请通过https://android.jlelse.eu/avoid-the-lag-caused-while-changing-fragment-activity-onnavigationitemselected-android-28bcb2528ad8。它真的很有帮助和有用。

希望你能从中找到更好的解决方案!

【讨论】:

  • 这个问题是关于导航组件库的
  • 不使用postDelayed,是不是有onTransitionDone之类的功能?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-15
  • 2020-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多