我(和其他许多人一样)在listview中获得顺畅的性能时遇到了问题。我相信我已经完成了本书的所有工作,但每次在屏幕上绘制新项目时,它仍然会显着滞后(约300-500毫秒)。
我正在使用viewHolder并尽可能多地重用UI元素(我认为)。有两个明确的瓶颈。
第一个是在newView()方法中膨胀XML代码的行。那是因为某种原因真的很慢(约300毫秒),我不知道这是否是预期的。
其次,bindView需要很长时间才能执行。这只是因为TextView.setText()方法调用占用了所有时间。 Other people have had the same problem我确实知道如果Android需要为每个列表项重新测量整个UI,这可能会很慢。但是,在将XML文件TextViews更改为固定大小后,我仍然会从.setText()获得非常慢的性能。我知道我可以将.setText放在Handler中,但在这种情况下看起来像是一个黑客。我会阻止列表滞后,但它不会更快地添加文本。我相信我应该能够将文本设置为快于~400毫秒,如果需要这么长时间我的UI /逻辑有问题。
但是如果没有进一步的麻烦,我会向您介绍源代码:希望能够巧妙地了解我做错了什么。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (ApplicationConfiguration.DEBUGGING)
Debug.startMethodTracing("getview");
View listViewItem;
EpisodeViewHolder holder;
Cursor itemCursor = (Cursor) getItem(position);
if (!itemCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position "
+ position);
}
mCurrentFeedItem = MyListItem.getByCursor(itemCursor);
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case TYPE_EXPAND:
listViewItem = newView(mContext, itemCursor, parent);
break;
default:
listViewItem = newView(mContext, itemCursor, parent);
break;
}
} else {
listViewItem = convertView;
}
bindView(listViewItem, mContext, itemCursor);
switch (type) {
case TYPE_EXPAND:
getPlayerViewHolder(position, listViewItem, itemCursor,
convertView, parent);
}
if (ApplicationConfiguration.DEBUGGING)
Debug.stopMethodTracing();
return listViewItem;
}
这是我的新视图
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mInflater.inflate(R.layout.episode_list, null); // here is the bottleneck
EpisodeViewHolder holder = new EpisodeViewHolder();
holder.icon = (ImageView) view.findViewById(R.id.list_image);
holder.mainTitle = (TextView) view.findViewById(R.id.title);
holder.subTitle = (TextView) view.findViewById(R.id.podcast);
holder.timeDuration = (TextView) view.findViewById(R.id.duration);
holder.currentPosition = (TextView) view.getTag(R.id.current_position);
holder.slash = (TextView) view.findViewById(R.id.time_slash);
holder.fileSize = (TextView) view.findViewById(R.id.filesize);
holder.stub = (ViewStub) view.findViewById(R.id.stub);
holder.playerView = (View) view.findViewById(R.id.stub_player);
view.setTag(holder);
return view;
}
我的bindView方法很长,但我会稍微缩短一下
@Override
public void bindView(View view, Context context, Cursor cursor) {
.....
final EpisodeViewHolder holder = (EpisodeViewHolder) view.getTag();
.....
// not a bottleneck
// Loads the image Async. The synchronous part of the call takes around 10%
// of the entire method
PicassoWrapper.load(mContext, i, holder.icon);
// This is the bottleneck
holder.mainTitle.setText(title);
}
XML UI
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_marginRight="7dip"
android:padding="0dip" >
<ImageView
android:id="@+id/list_image"
style="@style/PodcastImage" />
</LinearLayout>
<TextView
android:id="@+id/title"
style="@style/EpisodeHeaderFont"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_alignTop="@+id/thumbnail"
android:layout_toRightOf="@+id/thumbnail"
android:text="Podcast Title" />
<TextView
android:id="@+id/podcast"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_above="@+id/current_position"
android:layout_below="@id/title"
android:layout_marginTop="1dip"
android:layout_toRightOf="@+id/thumbnail"
android:ellipsize="end"
android:text="Podcast Name"
android:textSize="10dip" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/current_position"
style="@style/EpisodeMinorFont"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/thumbnail"
android:layout_toRightOf="@+id/thumbnail" />
<TextView
android:id="@+id/time_slash"
style="@style/EpisodeMinorFont"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/current_position"
android:layout_alignBottom="@+id/current_position"
android:layout_toRightOf="@+id/current_position"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:visibility="gone" />
<TextView
android:id="@+id/duration"
style="@style/EpisodeMinorFont"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/time_slash"
android:layout_alignBottom="@+id/time_slash"
android:layout_toRightOf="@+id/time_slash" />
<TextView
android:id="@+id/filesize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/duration"
android:layout_toRightOf="@+id/duration"
android:gravity="bottom|right"
android:text="0"
android:textSize="10dip"
android:textStyle="bold" />
</RelativeLayout>
<FrameLayout
android:id="@id/drag_handle"
android:layout_width="25dp"
android:layout_height="match_parent"
android:paddingBottom="30dp"
android:paddingTop="30dp" >
<LinearLayout
android:layout_width="7dp"
android:layout_height="fill_parent"
android:background="@drawable/drag_handle"
android:orientation="vertical"
android:tileMode="repeat" >
</LinearLayout>
</FrameLayout>
</LinearLayout>
<ViewStub
android:id="@+id/stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/stub_player"
android:layout="@layout/list_item_expanded" />