android - 优化抽屉和 Activity 启动速度

标签 android navigation-drawer

我正在使用 Google DrawerLayout

当一个项目被点击时,抽屉会平滑关闭,一个Activity会被启动。将这些 Activity 变成Fragment不是的一种选择。因此,启动 Activity 然后关闭抽屉也不是一种选择。关闭抽屉并同时启动 Activity 会导致关闭动画卡顿。

鉴于我想先顺利关闭它,然后启动 Activity,我遇到了用户单击抽屉项目和他们看到他们想要去的 Activity 之间的延迟问题。

这就是每个项目的点击监听器的样子。

final View.OnClickListener mainItemClickListener = new View.OnClickListener() {
    @Override
    public void onClick(final View v) {
        mViewToLaunch = v;
        mDrawerLayout.closeDrawers();
    }
};

我的activity也是DrawerListener,它的onDrawerClosed方法如下:

@Override
public synchronized void onDrawerClosed(final View view) {
    if (mViewToLaunch != null) {
        onDrawerItemSelection(mViewToLaunch);
        mViewToLaunch = null;
    }
}

onDrawerItemSelection 只是启动五个 Activity 之一。

我对 DrawerActivityonPause 什么都不做。

我正在对此进行检测,从调用 onClick 到 onDrawerClosed 结束的那一刻平均需要 500-650 毫秒。

有一个明显的延迟,一旦抽屉关闭,在相应的 Activity 启动之前。

我意识到有几件事正在发生:

  • 结束动画发生,这是几毫秒的时间(假设是 300)。

  • 那么在抽屉视觉关闭和它的监听器被触发之间可能会有一些延迟。我试图弄清楚到底发生了多少 by looking at DrawerLayout source但还没弄明白。

  • 然后是启动的 Activity 执行其启动生命周期方法所需的时间,直到(包括)onResume。我还没有对此进行检测,但我估计大约需要 200-300 毫秒。

这似乎是一个问题,走错路会付出相当高的代价,所以我想确保我完全理解它。

一种解决方案是跳过结束动画,但我希望保留它。

如何尽可能缩短过渡时间?

最佳答案

根据docs ,

Avoid performing expensive operations such as layout during animation as it can cause stuttering; try to perform expensive operations during the STATE_IDLE state.

您可以覆盖 ActionBarDrawerToggleonDrawerStateChanged 方法(实现 >DrawerLayout.DrawerListener),以便在抽屉完全关闭时执行昂贵的操作。

在 MainActivity 内部,

private class SmoothActionBarDrawerToggle extends ActionBarDrawerToggle {

    private Runnable runnable;

    public SmoothActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
    }

    @Override
    public void onDrawerOpened(View drawerView) {
        super.onDrawerOpened(drawerView);
        invalidateOptionsMenu();
    }
    @Override
    public void onDrawerClosed(View view) {
        super.onDrawerClosed(view);
        invalidateOptionsMenu();
    }
    @Override
    public void onDrawerStateChanged(int newState) {
        super.onDrawerStateChanged(newState);
        if (runnable != null && newState == DrawerLayout.STATE_IDLE) {
            runnable.run();
            runnable = null;
        }
    }

    public void runWhenIdle(Runnable runnable) {
        this.runnable = runnable;
    }
}

onCreate中设置DrawerListener:

mDrawerToggle = new SmoothActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.open, R.string.close);
mDrawerLayout.setDrawerListener(mDrawerToggle);

最后,

private void selectItem(int position) {
    switch (position) {
        case DRAWER_ITEM_SETTINGS: {
            mDrawerToggle.runWhenIdle(new Runnable() {
                @Override
                public void run() {
                    Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
                    startActivity(intent);
                }
            });
            mDrawerLayout.closeDrawers();
            break;
        }
        case DRAWER_ITEM_HELP: {
            mDrawerToggle.runWhenIdle(new Runnable() {
                @Override
                public void run() {
                    Intent intent = new Intent(MainActivity.this, HelpActivity.class);
                    startActivity(intent);
                }
            });
            mDrawerLayout.closeDrawers();
            break;
        }
    }
}

关于android - 优化抽屉和 Activity 启动速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18343018/

相关文章:

android - 抽屉导航总是膨胀的

java - 两个 ListView 不适用于 NavigationDrawer

android - 在 ProgressDialog 之后显示长任务的结果

android - Android Studio 中的模拟器分辨率问题

android - 我怎样才能得到IMEI号。我的设备通过 ionic ?

java - 应用程序可能在其主线程(抽屉导航)上做了太多工作

android - 二进制 XML 错误膨胀类 com.google.android.material.navigation.NavigationView

java - Android 实现可滑动的选项卡式布局

android - Activity 似乎是在应用程序对象之前创建的

android - 如何通过在抽屉外触摸来防止关闭抽屉导航