ListView 的优化及使用

本文介绍Android ListView组件与其适配器BaseAdapter的使用方法,重点讲解如何通过缓存convertView和使用ViewHolder模式来提高性能,减少不必要的资源加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

listview

BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置

但是在BaseAdapter中需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如

class MyAdapter extends BaseAdapter
    {
        private Context context;
        public MyAdapter(Context context)
        {
            this.context = context;
        }
        @Override
        public int getCount() {
            // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数)
            return 0;
        }

        @Override
        public Object getItem(int position) {
            // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项)
            return null;
        }

        @Override
        public long getItemId(int position) {
            // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id)
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Get a View that displays the data at the specified position in the data set.
            return null;
        }
        
    }
这个getView中的代码有很多种处理方式,比如
简单的方法1   效率低, 没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能

<span style="font-size:14px;">public View getView(int pos, View convertView,
ViewGroup parent){
View item = mInflater.inflate(R.layout.list_item, null);
((TextView) item.findViewById(R.id.text)).
setText(DATA[pos]);
((ImageView) item.findViewButId(R.id.icon)).
return item;
}</span>

使用方法2   通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

<span style="font-size:14px;">public View getView(int pos, View convertView,
ViewGroup parent){
if (convertView == null) {
convertView = mInflater.inflate(
R.layout.list_item, null);
}
((TextView) convertView.findViewById(R.id.text)).
setText(DATA[pos]);
((ImageView) convertView.findViewButId(R.id.bt)).
setImageBitmap(xxx);
return convertView;
}</span>

使用方法3   通过convertView+ViewHolder来实现

原理:创建一个小型的数据结构在你的应用程序中,这个数据结构会把数据(每个item上的视图)静态存储在程序中。当ConventView为空,会创建ViewHolder实例,之后吧ViewHolder中各个实例找到。再把holder作为conventview的tag设置上去。当有一个conventview需要返回给listview'时就用conventview来获取tag,这样就可以直接获取TextView和Button'了,节省了findview'byid的操作。

在这里,官方给出了解释

提升Adapter的两种方法

To work efficiently the adapter implemented here uses two techniques:
-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary

(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)
-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary

(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)
ViewHolder类的作用
-The ViewHolder pattern consists in storing a data structure in the tag of the view
returned by getView().This data structures contains references to the views we want to bind data to,
thus avoiding calling to findViewById() every time getView() is invoked

(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们

要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())

<span style="font-size:14px;">static class ViewHolder {
TextView text;
Button bt;
}
public View getView(int pos, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(
R.id.text));
holder.icon = (ImageView) convertView.findViewButId(
R.id.icon));
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[xxx]);
holder.icon.setImageBitmap(xxx);
return convertView;
}</span>
当listview中出现button或者imagebutton的时候会发生焦点冲突的情况

listview中添加Button后item不能点击的解决办法

1.在ItemView配置的xml文件中的根节点添加属性android:descendantFocusability="blocksDescendants"

2.在要添加事件的控件上添加android:focusable="false

listview中button的点击事件

<span style="font-size:14px;">public class MainActivity extends Activity {
	ListView lv;		
	class ViewHolder{
		ImageView iv;
		Button bt;	
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		lv = (ListView) findViewById(R.id.lv);
		lv.setAdapter(new myAdapter());
	}	
	class myAdapter extends BaseAdapter{
		
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return 10;
		}
		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return 0;
		}
		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return 0;
		}
		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			LayoutInflater inflate = LayoutInflater.from(MainActivity.this);
			ViewHolder holder = new ViewHolder();
			if (convertView==null){
				convertView = inflate.inflate(R.layout.item,null);
				holder.bt = (Button) convertView.findViewById(R.id.bt);
				holder.iv = (ImageView) convertView.findViewById(R.id.iv);
				convertView.setTag(holder);
			} else{				
				holder = (ViewHolder) convertView.getTag();				
			}
			holder.iv.setImageResource(R.drawable.ic_launcher);
			holder.bt.setText("按钮"+position);
			 holder.bt.setOnClickListener(new OnClickListener(){

				@Override
				public void onClick(View v) {
					Toast.makeText(MainActivity.this,"您选择了标题:" + position, Toast.LENGTH_SHORT).show();
				}			 
			 });
			return convertView;
		}		
	}
}</span>

simpleAdapter的使用

public class MainActivity extends Activity {
	ListView lv;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		lv = (ListView) findViewById(R.id.lv);
		List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
		Map<String,Object> item1 = new HashMap<String,Object>();
		item1.put("image",R.drawable.computer);
		item1.put("text", "1");
		
		Map<String,Object> item2 = new HashMap<String,Object>();
		item2.put("image",R.drawable.thinkpad);<span style="color: rgb(0, 130, 0); font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 18px;">//把数据填充到item1和item2中。</span>
		item2.put("text", "2");
		
		Map<String,Object> item3 = new HashMap<String,Object>();
		item3.put("image",R.drawable.home);
		item3.put("text", "3");
		for(int x = 0;x<10;x++){
			data.add(item1);
			data.add(item2);
			data.add(item3);			
		}	
	lv.setAdapter(new SimpleAdapter(this, data, R.layout.item, new String[]{"image","text"}, new int[]{R.id.iv,R.id.tv})<span style="white-space:pre">		</span>);
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值