在我的Activity我有一个从这个XML布局中膨胀的GridView :
<GridView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:columnWidth="@dimen/thumbnail_size" android:gravity="fill" android:horizontalSpacing="16dp" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="16dp" />其中的项目是RelativeLayout ,每个都设置为固定的高度。 在分析我的Activity ,我注意到当我输入ActionMode ,它会导致一个度量传递,这会导致重新测量GridView 。 GridView反过来多次调用我的适配器上的getView()来测量所有子视图。 这是不必要的工作,因为(a)哪些孩子可见并没有改变,所以它已经拥有了所需的所有观点; (b)儿童意见均无法改变规模。
我知道ListView和GridView有很多技巧可以避免在简单的情况下工作,这似乎是他们可能有优化的特殊情况。 有什么我可以在GridView上设置,以帮助它意识到这里不需要再次调用getView() ? 或者,我可以向上移动堆栈并避免在进入和离开ActionMode时措施完全通过吗? 为了清楚getView() ,我的适配器的行为是正确的,并且getView()调用不会导致我出现问题:我只是想让我的应用程序烧掉更少的周期。
注意即使我将项目设置为具有固定宽度和高度,并使用以下内容替换GridView ,它也不会更改getView()调用的数量(但它确实使我的Activity变得丑陋)。
<GridView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:descendantFocusability="beforeDescendants" android:columnWidth="@dimen/thumbnail_size" android:horizontalSpacing="16dp" android:numColumns="3" android:stretchMode="none" android:verticalSpacing="16dp" />In my Activity I have a GridView inflated from this XML layout:
<GridView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:columnWidth="@dimen/thumbnail_size" android:gravity="fill" android:horizontalSpacing="16dp" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="16dp" />The items inside it are RelativeLayouts, each set to a fixed height. While profiling my Activity, I noticed that when I enter an ActionMode, it causes a measure pass, which causes the GridView to be re-measured. The GridView in turn calls getView() on my adapter many times to measure all of the child views. This is unnecessary work, since (a) which children are visible hasn't changed, so it already has all the views it needs; and (b) none of the child views can change size.
I know that ListView and GridView have lots of tricks they can do to avoid work in easy cases, and this seems like the kind of special case they might have an optimization for. Is there something I can set on the GridView to help it realise there's no need to call getView() again here? Alternatively, can I go higher up the stack and avoid the measure pass completely when entering and leaving an ActionMode? Just to be clear, the behaviour of my adapter is correct, and the getView() calls aren't causing me a problem: I just want my app to burn fewer cycles.
N.B. Even if I set the items to have fixed width as well as height, and replace the GridView with the following, it doesn't change the number of getView() calls (but it does make my Activity ugly).
<GridView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:descendantFocusability="beforeDescendants" android:columnWidth="@dimen/thumbnail_size" android:horizontalSpacing="16dp" android:numColumns="3" android:stretchMode="none" android:verticalSpacing="16dp" />最满意答案
使用ListView而不是GridView。 看一下实现(API 16):
ListView.onMeasure(...) { ... if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED)) { final View child = obtainView(0, mIsScrap); ... }和
GridView.onMeasure(...) { ... final int count = mItemCount; if (count > 0) { final View child = obtainView(0, mIsScrap); ... }它看起来像一个bug。
Use ListView instead of GridView. Look at the implementation (API 16):
ListView.onMeasure(...) { ... if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED)) { final View child = obtainView(0, mIsScrap); ... }and
GridView.onMeasure(...) { ... final int count = mItemCount; if (count > 0) { final View child = obtainView(0, mIsScrap); ... }It looks like a bug.
更多推荐
发布评论