最近公司需要改进tab之间切换的速度,所以我用hierarchyviewer工具查看了一下,发现每个tab的onmeasure+onlayout+ondraw的时间加起来为200ms左右,所以导致了tab之间切换的非常不流畅。

怎么优化呢?先看看android.widget.ViewFlipper类,继承自android.widget.ViewAnimator,是一个为tab之间切换实现简单动画的一个viewgroup,但是我们公司的软件tab之间的切换根本就没有动画,也就是说我们只是将ViewFlipper类作为一个承载view的容器,用户点击每个tab,从而显示相应的view,显然这没有使用ViewFlipper的意义,但是为什么切换的速度这么慢呢?我们去看看ViewFlipper的源码:

ViewFlipper源码

没有找到 setDisplayedChild(int)函数,那就在父类里面,找到父类:

 /**     * Sets which child view will be displayed.     *     * @param whichChild the index of the child view to display     */    @android.view.RemotableViewMethod    public void setDisplayedChild(int whichChild) {        mWhichChild = whichChild;        if (whichChild >= getChildCount()) {            mWhichChild = 0;        } else if (whichChild < 0) {            mWhichChild = getChildCount() - 1;        }        boolean hasFocus = getFocusedChild() != null;        // This will clear old focus if we had it        showOnly(mWhichChild);        if (hasFocus) {            // Try to retake focus if we had it            requestFocus(FOCUS_FORWARD);        }    }

从代码里面可以简单的看出来,showOnly()函数是重点,转到showOnly函数

void showOnly(int childIndex, boolean animate) {        final int count = getChildCount();        for (int i = 0; i < count; i++) {            final View child = getChildAt(i);            if (i == childIndex) {                if (animate && mInAnimation != null) {                    child.startAnimation(mInAnimation);                }                child.setVisibility(View.VISIBLE);                mFirstTime = false;            } else {                if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) {                    child.startAnimation(mOutAnimation);                } else if (child.getAnimation() == mInAnimation)                    child.clearAnimation();                child.setVisibility(View.GONE);            }        }    }
一个循环,把所有的子view都执行移出动画和移入动画,并且同时设置visibility,所以我个人觉得是不是这里循环有点耗时?


于是我就换成了tabhost,嗯!就是这个感觉,时间上感觉少了不少,切换tab的速度也快了很多,tabhost的实现主要是

public void setCurrentTab(int index) {        if (index < 0 || index >= mTabSpecs.size()) {            return;        }        if (index == mCurrentTab) {            return;        }        // notify old tab content        if (mCurrentTab != -1) {            mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();        }        mCurrentTab = index;        final TabHost.TabSpec spec = mTabSpecs.get(index);        // Call the tab widget's focusCurrentTab(), instead of just        // selecting the tab.        mTabWidget.focusCurrentTab(mCurrentTab);        // tab content        mCurrentView = spec.mContentStrategy.getContentView();        if (mCurrentView.getParent() == null) {            mTabContent                    .addView(                            mCurrentView,                            new ViewGroup.LayoutParams(                                    ViewGroup.LayoutParams.MATCH_PARENT,                                    ViewGroup.LayoutParams.MATCH_PARENT));        }        if (!mTabWidget.hasFocus()) {            // if the tab widget didn't take focus (likely because we're in touch mode)            // give the current tab content view a shot            mCurrentView.requestFocus();        }        //mTabContent.requestFocus(View.FOCUS_FORWARD);        invokeOnTabChangeListener();    }

tabwidget的focusCurrentTab函数:

public void setCurrentTab(int index) {        if (index < 0 || index >= getTabCount() || index == mSelectedTab) {            return;        }        if (mSelectedTab != -1) {            getChildTabViewAt(mSelectedTab).setSelected(false);        }        mSelectedTab = index;        getChildTabViewAt(mSelectedTab).setSelected(true);        mStripMoved = true;        if (isShown()) {            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);        }    }
setSelected会调用到view的 invalidate函数重新绘制


流程就是这样,用起来的效果也是tabhost比较快,个人觉得如果不需要tab之间切换的移出和移入动画,

用viewFlipper就大材小用了,用tabhost即可


更多相关文章

  1. changeConfig配置 以及对activity生命周期的影响
  2. Android(安卓)基于TranslateAnimation 的动画动态菜单(非系统menu
  3. Android(安卓)在低版本sdk中没有getSupportedPreviewSizes和getS
  4. Android(安卓)ApiDemos示例解析
  5. Android下可用的wide char 函数库
  6. android: Can't create handler inside thread that has not cal
  7. 关于Android(安卓)Settings中的八个问题
  8. Android使用Intent返回上一个Activity时StackOverflowError
  9. Android,一个函数实现上传文件(单个,多文件)

随机推荐

  1. Android的进程,线程模型
  2. Android设备的ID
  3. Android新手入门 FAQ
  4. sscanf函数引起android 5.0卡死,C++中慎用
  5. Android体系框架
  6. 如何学习android高级编程
  7. Android之Window类简介
  8. android访问网络,下载图片,并设置UI
  9. Android:你要的WebView与 JS 交互方式 都
  10. 如何学习android高级编程