通过NavigationDrawer导航时,Android导航组件存在滞后

时间:2019-07-11 13:40:56

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

我正在将我的应用程序更新为“导航体系结构组件”,我发现它具有替换片段的滞后性,这在导航抽屉中可见,但无法顺利关闭。

直到现在,我一直在使用这种方法:

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?

非常感谢您。

2 个答案:

答案 0 :(得分:6)

在撰写此答案时,我正在解决此问题。经过一些测试,我得出的结论是我正在创建的片段中立即执行的代码(例如初始化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()
        }
    }
} 

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

答案 1 :(得分:0)

避免在NavigationItemSelected- Android上更改Fragment / Activity时引起的延迟

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

我已经在许多应用程序中看到,当我们从导航菜单中更改选项时,我们发现它滞后了,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。确实有帮助和有用。

希望您能找到更好的解决方案!