Cache mechanism of ListView in Android

First, the operation mechanism of ListView
1. Use match_parent to define the height and width properties of ListView.
To define the height and width of the ListView control, avoid using wrap_content, otherwise it will cause BaseAdapter.getView to be called repeatedly N times, try to use match_parent or fixed values ​​to set height and width.


2. Cached list items
The ListView control is designed with a layout object that only creates and displays the list items in the current screen (the layout object is saved by the convertView parameter of the BaseAdapter.getView method).


For example, if ten list items are displayed on one screen (including some list items displayed on the screen), only ten convertViews are created, and ListView will repeatedly use these ten convertViews to display the contents of the current list items.
When scrolling up, when the first convertView moves off the screen, the convertView will appear from the bottom of the screen. Similarly, when scrolling down, if the convertView at the bottom of the screen moves out of the screen, the convertView moves out of the screen, and the convertView enters the screen from the top.

Tip:
One screen does not necessarily display ten list items, the specific number depends on the height of the list item layout and the height of the device.



Example case:

 

package com.jxust.day05_08_listviewoptimize;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

	ListView mlvContact;
	List<ContactBean> mContacts;
	ContactAdapter mAdapter;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate (savedInstanceState);
		setContentView(R.layout.activity_main);
		initData ();
		initView();
	}

	private void initView() {
		mlvContact = (ListView) findViewById(R.id.lvContact);
		mAdapter = new ContactAdapter(mContacts, this); // create the adapter	
		mlvContact.setAdapter(mAdapter); // configure the adapter
	}

	private void initData() {
		String[] names = getResources().getStringArray(R.array.names);
		String[] phones = getResources().getStringArray(R.array.phones);
		mContacts = new ArrayList<ContactBean>();
		for(int i = 0; i < phones.length;i++){
			ContactBean contact = new ContactBean(names[i],phones[i]);
			mContacts.add(contact);
		}
	}

	class ContactAdapter extends BaseAdapter{
		List<ContactBean> contacts;
		MainActivity context;
		
		public ContactAdapter(List<ContactBean> contacts, MainActivity context) {
			super();
			this.contacts = contacts;
			this.context = context;
		}

		// length of inner set
		@Override
		public int getCount() {
			
			return contacts.size();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			Log.i("main", "position="+position);
			ViewHolder holder = null;
			if(convertView == null){// Indicates that the first screen has not yet created a list item, and convertView means null
				convertView = View.inflate(context, R.layout.item_contact, null); //Create a layout
				holder = new ViewHolder();
				//Assign the properties of the layout obtained by convertView to the ViewHolder object
				holder.tvName = (TextView) convertView.findViewById(R.id.tvName);	
				holder.tvPhone = (TextView) convertView.findViewById(R.id.tvPhone);
				convertView.setTag(holder); // tag is an attribute in View and is of type Object
			}else{// Later scrolling, other list items appear
				// This avoids repeated parsing and improves efficiency
				holder = (ViewHolder) convertView.getTag();
			}
			// Get the current contact
			ContactBean contact = contacts.get(position);
			holder.tvName.setText(contact.getName());
			holder.tvPhone.setText(contact.getPhone());
			return convertView;
		}
		
		// Store the two components in item_contact.xml
		class ViewHolder{
			TextView tvName,tvPhone;
		}

	}
}

 

 

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <!-- The width and height in the listView should be set to match_parent to avoid repeated calls of BaseAdapter.getView-->
    <ListView
        android:id="@+id/lvContact"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="#ccc"
        android:dividerHeight="10dp" />

</RelativeLayout>

 

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Zhang Fei"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tvPhone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text="13011335577"
        android:textSize="20sp" />

</LinearLayout>

 

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Day05_08_ListViewOptimize</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string-array name="names">
        <item>Zhang Fei</item>
        <item>Faye Wong</item>
        <item>Liu Yifei</item>
        <item>Once Upon a Time</item>
        <item>Li Fei</item>
        <item>陈菲</item>
        <item>赵菲</item>
        <item>田菲</item>
        <item>郑菲</item>
        <item>邓菲</item>
        <item>Yue Fei</item>
        <item>郝菲</item>
        <item>Coffee</item>
        <item>啡啡</item>
    </string-array>
    <string-array name="phones">
        <item>13011335577</item>
        <item>13155335577</item>
        <item>13311335577</item>
        <item>13511335577</item>
        <item>13711335577</item>
        <item>13811335577</item>
        <item>13911335577</item>
        <item>15011335577</item>
        <item>13111335577</item>
        <item>18211335577</item>
        <item>18911335577</item>
        <item>13088335577</item>
        <item>13399335577</item>
        <item>13078335577</item>
    </string-array>
</resources>

 

 

 

Through observation in logcat, it is found that after the processing of convertView, repeated parsing is avoided, thereby improving efficiency.

 

And, pay special attention to the values ​​of width and height in activity_main.xml, we'd better choose match_parent



 

 

otherwise:

 

It was found that BaseAdapter.getView was repeatedly called 3 times, which would lead to a waste of resources.

 

 

but if we use match_parent

 



 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326941291&siteId=291194637