您的位置:首页 > 移动开发 > Android开发

Android中ListView的缓存机制

2016-05-13 17:09 423 查看

一、ListView 的运行机制
1、使用match_parent 定义ListView 的高度和宽度属性。
定义 ListView 控件的高度和宽度要避免使用wrap_content,否则会导致BaseAdapter.getView 重复调用N次,尽量使用match_parent或固定值设置height和width。


2、缓存列表项
ListView 控件在设计上采用了只创建并显示当前屏幕中的列表项的布局对象(该布局对象由BaseAdapter.getView方法的convertView参数保存)。


例如:一屏显示十个列表项(包括部分显示在屏幕上的列表项),则只创建十个convertView,ListView会反复使用这十个convertView显示进入当前的列表项的内容。
在向上滚屏时,当第一个convertView移出屏幕,该convertView将从屏幕下边出现。同理,在向下滚屏时,若屏幕最下边的convertView移出屏幕,该convertView移出屏幕,该convertView从最上边进入屏幕。

提示:
一屏不一定显示十个列表项,具体多少根据列表项布局的高度和设备的高度而定。



实例案例:

 

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);	//	创建适配器
mlvContact.setAdapter(mAdapter);	//	配置适配器
}

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;
}

// 内部集合的长度
@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){// 表示第一屏尚未创建列表项,convertView就表示的是null
convertView = View.inflate(context, R.layout.item_contact, null);	//创建布局
holder = new ViewHolder();
//把convertView获取到布局的属性赋给ViewHolder对象
holder.tvName = (TextView) convertView.findViewById(R.id.tvName);
holder.tvPhone = (TextView) convertView.findViewById(R.id.tvPhone);
convertView.setTag(holder);	//	tag是View中一个属性,是Object类型的
}else{// 以后的滚动,出现其它的列表项
// 这样就可以避免重复解析,提高效率
holder = (ViewHolder) convertView.getTag();
}
// 取出当前的联系人
ContactBean contact = contacts.get(position);
holder.tvName.setText(contact.getName());
holder.tvPhone.setText(contact.getPhone());
return convertView;
}

// 存放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" >

<!-- listView中的width和height要设置成match_parent可以避免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="张飞"
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>张飞</item>
<item>王菲</item>
<item>刘亦菲</item>
<item>黄飞鸿</item>
<item>李菲</item>
<item>陈菲</item>
<item>赵菲</item>
<item>田菲</item>
<item>郑菲</item>
<item>邓菲</item>
<item>岳飞</item>
<item>郝菲</item>
<item>咖啡</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>

 

 

 

通过在logcat观察发现,经过对convertView的处理,避免了重复解析,从而提高了 4000 效率。

 

并且,特别要注意的是activity_main.xml中有关width和height的取值,我们最好是选择match_parent



 

 

否则:

 

发现,BaseAdapter.getView被重复调用了3次,这样就会导致资源的浪费。

 

 

但是如果我们使用match_parent

 



 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: