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)関数が見つかりません.親の中に親が見つかります.
コードから簡単に分かるように、showOnly()関数がポイントで、showOnly関数に移動します
そこでtabhostに変えて、うん!この感覚では、時間的な感覚が少なくなり、tabを切り替える速度も速くなり、tabhostの実現は主に
tabwidgetのfocusCurrentTab関数:
invalidate関数の再描画
流れはこのようにして、使う効果もtabhostの方が速く、個人的にはtab間の切り替えの移動や移動が必要でなければ、
viewFlipperで大材小用、tabhostでOK
どのように最適化しますか?まず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