Android Navigation Component has lag when navigating through NavigationDrawer

Jav*_*ado 20 android navigation-drawer navigationview android-architecture-navigation

I am updating my app to Navigation Architecture Components and I see that it has a lag replacing fragments which is visible in the NavigationDrawer that does not close smoothly.

Until now, I was following this approach:

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

所以我导航onDrawerClosed而不是进入onNavigationItemSelected以避免故障。

这是一个非常普遍的问题,但它又回来了。使用导航组件,它再次滞后,我没有看到在onDrawerClosed.

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

Android 上的导航抽屉滞后

DrawerLayout 的项目点击 - 什么时候更换片段合适?

非常感谢。

Uro*_*vic 7

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

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

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

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

interface StartFragmentListener {
    fun configureFragment()
}
Run Code Online (Sandbox Code Playgroud)

在活动设置 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()
        }

    })
}
Run Code Online (Sandbox Code Playgroud)

通知一个片段抽屉已经关闭并且它可以执行导致延迟的操作:

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

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

}
Run Code Online (Sandbox Code Playgroud)

如果您没有从抽屉导航到片段(例如按后退按钮),您还需要通知片段执行其操作。我们将实现 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)
}
Run Code Online (Sandbox Code Playgroud)

在片段中:

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

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