android viewflipperとtabhost効率の比較

4441 ワード

最近、会社はtab間の切り替え速度を改善する必要があるので、hierarchyviewerツールで調べてみると、tabごとのonmeasure+onlayout+ondrawの時間を合わせて200 ms程度なので、tab間の切り替えが非常にスムーズではないことがわかりました.
どのように最適化しますか?まずandroidを見てみましょうwidget.ViewFlipperクラスはandroidから継承されています.widget.ViewAnimatorは、tab間の切り替えのために簡単なアニメーションを実現するviewgroupですが、当社のソフトウェアtab間の切り替えにはアニメーションがありません.つまり、私たちはViewFlipperクラスをviewを載せる容器としているだけで、ユーザーはtabをクリックして対応するviewを表示します.これはView Flipperを使用する意味がありません.しかし、なぜ切り替えの速度がこんなに遅いのでしょうか.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でOK