ListView 的优化及使用

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

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




【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究不仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换不同算法或测试系统进一步拓展研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值