gpt4 book ai didi

android - 由于 View 测量导致布局性能不佳?

转载 作者:太空宇宙 更新时间:2023-11-03 13:27:26 27 4
gpt4 key购买 nike

我遇到了性能问题,我认为这是由衡量我的观点引起的。我的布局是以编程方式构建的,因此我无法显示我的布局的 xml。但这里有一些可能会导致问题的观点:

  • 一个用于包裹所有内容的 ScrollView(宽度:MATCH_PARENT,高度:MATCH_PARENT)
  • 包含所有不同内容部分的 LinearLayout(宽度:MATCH_PARENT,高度:MATCH_PARENT,前一个 View 的 subview )
  • 两个 LinearListViews (LinearLayout) 异步填充(宽度:MATCH_PARENT,高度:WRAP_CONTENT,前一个 View 的 subview )

问题似乎只在我填充 LinearListView 时出现;添加 View 似乎会触发 View.measure 被多次调用:

Method profiling result

为什么多次调用 View.measured?具有 MATH_PARENT 大小的 LinearLayout 意味着它不必在添加子项时再次测量它,对吗?

我不太确定如何防止这种情况发生,或者如何调试问题。我尝试将 LinearListView 的可见性设置为 GONE,直到所有项目都添加完毕,但这并没有什么不同。

我希望我提供了足够的信息,以便有人为我指明正确的方向。

编辑 #1 (07/01):

下面是用于 LinearListViews 的适配器基类的一些部分:

public abstract class DataProviderAdapter<T> extends BaseAdapter
{
...

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
T item = getItem(position);

Log.d(TAG, "getView(): Position: " + position + ", ConvertView: "
+ (convertView == null ? "null" : convertView) + ", TotalCount: " + getCount());

if (row == null) {
row = buildRow(position);
markRowAsLoading(row);
}

if (item == null) {

if (convertView != null) {
markRowAsLoading(row);
}

int skip;
if (itemsRequestParams != null) {
int pageSize = itemsRequestParams.getTake();

// determine how many items to skip
skip = position - (position % pageSize);
}
else {
skip = 0;
}

// if the page isn't already being fetched
if (!pagesReceiving.contains(skip)) {
pagesReceiving.add(skip);
AsyncTaskUtil.executeMultiThreaded(new ReceiveItemsTask(), skip);
}
}
else {
Log.d(TAG, getClass().getSimpleName() + " - PrepareRow: " + getItemId(position)
+ ", Pos: " + position);
prepareRow(row, item, position);
}
return row;
}

protected void processDataResult(int skip, DataResult<T> result)
{
if (result instanceof GroupedDataResult<?>) {
GroupedDataResult<T> groupedResult = (GroupedDataResult<T>)result;
totalItemCount = groupedResult.getTotalGroupCount() + groupedResult.getTotalItemCount();
}
else {
totalItemCount = result.getTotalItemCount();
}

for (int i = 0; i < result.getItems().size(); i++) {
itemList.put(skip + i, result.getItems().get(i));
}

Log.d(TAG, "processDataResult(" + skip + ")");
notifyDataSetChanged();
}

static protected class CellHolder
{
public ProgressBar ProgressSpinner;
public List<android.widget.ImageView> Images;
public List<TextView> Labels;
private final HashMap<String, Object> _extras = new HashMap<String, Object>();

public void putExtra(String key, Object value)
{
_extras.put(key, value);
}

@SuppressWarnings("unchecked")
public <T> T getExtra(String key)
{
return _extras.containsKey(key) ? (T)_extras.get(key) : null;
}
}

...

private class ReceiveItemsTask extends AsyncTask<Integer, Void, DataResult<T>>
{
private int skip;

@Override
protected DataResult<T> doInBackground(Integer... params)
{
skip = params[0];
DataResult<T> items = getItems(skip);
Log.d(TAG, "doInBackground(" + skip + ")");
return items;
}

@Override
protected void onPostExecute(DataResult<T> result)
{
Log.d(TAG,
"onPostExecute("
+ (result == null ? "null" : result.getItems().size() + "/"
+ result.getTotalItemCount()) + ")");
if (result == null) {
return;
}
processDataResult(skip, result);
Log.d(TAG, "onPostExecute end");
}
}
}

编辑 #2 (07/01):

我继承了 RelativeLayout 并覆盖了 onMeasure,这样我就可以记录正在测量的 View 以及测量顺序。这些是结果:

07-01 15:37:37.434: V/DefaultLayout(8172): DefaultLayout.onMeasure
07-01 15:37:37.434: V/DefaultLayout(8172): TabView.onMeasure
07-01 15:37:37.434: V/DefaultLayout(8172): ItemDetailsContainerView.onMeasure
07-01 15:37:37.438: V/DefaultLayout(8172): HeaderView.onMeasure
07-01 15:37:37.438: V/DefaultLayout(8172): ItemDetailsInfoFieldsLayout.onMeasure
07-01 15:37:37.438: V/DefaultLayout(8172): ItemReviewTableView.onMeasure
07-01 15:37:37.438: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.438: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.442: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.446: V/DefaultLayout(8172): ItemReviewTableView.onMeasure
07-01 15:37:37.446: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.446: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.446: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.446: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.450: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.450: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.450: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.450: V/DefaultLayout(8172): InfoFieldsLayout.onMeasure
07-01 15:37:37.450: V/DefaultLayout(8172): RelatedItemsTableView.onMeasure
07-01 15:37:37.454: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.458: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.462: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.466: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.470: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.474: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.478: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.478: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.482: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.482: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.486: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.486: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.490: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.490: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.494: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.494: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.498: V/DefaultLayout(8172): RelatedItemsTableView.onMeasure
07-01 15:37:37.498: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.498: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.502: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.502: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.506: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.506: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.510: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.510: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.514: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.514: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.518: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.518: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.522: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.522: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.526: V/DefaultLayout(8172): RatingView.onMeasure
07-01 15:37:37.526: V/DefaultLayout(8172): RatingView.onMeasure
...

这个列表会持续一段时间。但对我来说似乎很奇怪的是,它从测量顶 View (DefaultLayout.onMeasure) 开始,然后还测量所有 subview (所有 View )。它多次执行此操作!

是什么导致在顶 View 上调用 onMeasure?

编辑 #3 (07/02):

难道是notifyDataSetChanged()触发了顶 View 的测量?

编辑 #4 (07/03):

是的,似乎 notifyDataSetChanged() 触发了要测量的顶级 View (我能够在新的测试项目中重现这一点)。由于我的适配器的工作方式,notifyDataSetChanged() 被多次调用。

当我调用 notifyDataSetChanged() 时测量所有 View 的原因是什么?有什么办法可以防止这种情况发生吗?

最佳答案

你没有说相对布局从哪里来,这是列表的包装器吗?

根据 Romain Guy 的说法,相对布局总是进行两次测量,因此这可能会导致一些速度下降。您甚至有嵌套的相对布局吗?显然,这可能具有指数时间复杂度。

请参阅此答案以供引用(以及指向他实际所说的 Google io 视频的链接):

https://stackoverflow.com/a/17496262/1281144

关于android - 由于 View 测量导致布局性能不佳?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17403102/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com