android viewflipper和tabhost效率对比

        最近公司需要改进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即可


你可能感兴趣的:(android)