A brief discussion on some optimization methods of ListView control performance in Android development
- 2020-12-26 05:52:25
- OfStack
ListView optimization 1 is one of those age-old questions that can never be ignored in an interview or in regular development, so in this article we'll look at how to maximize ListView's performance.
1. Minimize the use of logic in the getView method in adapter
2. Avoid GC as much as possible
3. Not loading images while swiping
4. Set scrollingCache and animateCache of ListView to false
5. The fewer layout levels you have in item, the better
6. Use ViewHolder
So let's look at some of these
1. Minimize the use of logic in the getView method in adapter
Don't write too much logic in your getView(), we can put it somewhere else, for example:
getView () before optimization:
@Override
public View getView(intposition, View convertView, ViewGroup paramViewGroup) {
Object current_event = mObjects.get(position);
ViewHolder holder =null;if(convertView ==null) {
holder =newViewHolder();
convertView = inflater.inflate(R.layout.row_event,null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
// The logic here is problematic
if(doesSomeComplexChecking()) {
holder.ThreeDimention.setVisibility(View.VISIBLE);
}else{
holder.ThreeDimention.setVisibility(View.GONE);
}
// This is to set up image Parameters, each time getView This code is executed when the method executes, which is obviously problematic
RelativeLayout.LayoutParams imageParams =newRelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams);
returnconvertView;
}
Optimized getView () :
@Override
public View getView(intposition, View convertView, ViewGroup paramViewGroup) {
Object object = mObjects.get(position);
ViewHolder holder =null;if(convertView ==null) {
holder =newViewHolder();
convertView = inflater.inflate(R.layout.row_event,null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
// Setting parameters mentioned here, only the 1 It will be executed the second time, and then reused
RelativeLayout.LayoutParams imageParams =newRelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}// We go directly through the object's getter The method replaces those logical judgments that were executed somewhere else holder.ThreeDimension.setVisibility(object.getVisibility());returnconvertView;
}
2.GC garbage collector
GC executes frequently when you create a large number of objects, so don't create many objects in the getView () method. The best optimization is not to create any objects other than ViewHolder. If you find that "GC has freed some memory" occurs frequently in your log, then something is wrong with your program. You can check 1 below:
a) Is the hierarchy of the item layout too deep
Whether a large number of objects exist in the b) getView () method
c) Layout properties of ListView
3. Load the picture
If your ListView needs to display images downloaded from the network, we should not load the image when ListView slides, which will make ListView become stuck, so we need to monitor the status of ListView in the listener again. If you slide, stop loading the image, if there is no slide, start loading the image
listView.setOnScrollListener(newOnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView listView,intscrollState) {
// Stop loading images
if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
imageLoader.stopProcessingQueue();
}else{
// Start loading images
imageLoader.startProcessingQueue();
}
}
@Override
public void onScroll(AbsListView view,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {
// TODO Auto-generated method stub}
});
4. Set scrollingCache and animateCache of ListView to false
scrollingCache:scrollingCache is essentially drawing cache. You can have one View save its own drawing in cache (save as one bitmap) so that the next time you display View you don't have to redraw it, but take it out of cache. drawing cahce is disabled by default because it consumes too much memory, but it is actually smoother than drawn. In ListView, scrollingCache is turned on by default and we can turn it off manually.
animateCache:ListView turns animateCache on by default, which consumes a lot of memory and therefore calls GC frequently, so we can turn it off manually
ListView before optimization
<android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:smoothScrollbar="true"
android:visibility="gone"/>
Optimized ListView
<android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:scrollingCache="false"
android:animationCache="false"
android:smoothScrollbar="true"
android:visibility="gone"/>
5. Reduce the depth of the item layout
We should try to minimize the depth of the item layout because sliding ListView directly results in measurement and drawing, which is a huge waste of time, so we should remove some unnecessary layout nesting. Reduce item layout depth
6. Use ViewHolder
You should be familiar with this, but don't underestimate the ViewHolder, it can greatly improve the performance of our ListView
We have finished with ListView optimizations. If you have not achieved these basic optimizations in your project, then you have a problem with ListView and have a lot of potential for improvement. When you use ListView in the future, 1 must take these points into account to get the most out of it.
The attached:
In addition, if a performance issue is found, the following common issues should also be noted:
1.. convertView does not use setTag and getTag methods in Adapter's getView method;
2. In getView method, the assignment after ViewHolder is initialized, or the display state and background of multiple controls are not optimized, or there are complex calculations and time-consuming operations;
3. In getView method, row of inflate is too deeply nested (the layout is too complex) or there are large pictures or backgrounds in the layout;
4.Adapter is unnecessary or unreasonable.
5.listview is nested by multiple layers, and multiple onMessure results in delays. If multi-layer nesting cannot be avoided, it is recommended to set the height and width of listview to fill_parent. If listview is inherited by code, please do not forget to add LayoutPrams to your inherited class. Note that the height and width are fill_parent. In the past I usually set listview to fill_parent, but this time I set it to wrap_content. The problem with this is that ListView did not get to the actual height, and it has to be determined according to the calculation. Every calculation should trigger the render of listview, so the number of calls to getview is several times higher than normal. So in general, I recommend always setting the height of listiview in the layout file to fill_parent (or match_parent). This is not just a matter of the number of calls to getview, but also the efficiency of the layout.