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.


Related articles: