listview性能优化,总结六点

大体总结:
1.listView 宽高不能是wrap_content否则会调用 measureheightofchilden会调用两次 (浪费)
2.covertview(xml由infaler填充生成)什么时候为null 什么时候不为null   covertview的复用
3.调用getView方法的时候  convertView为空 infater调用个参数的  viewHolder的使用  减少findView的使用,保存引用
4. ViewHolder防错位   滑动之后  0变成10 
5.设置listView的手势监听器   isfling会有大量视图产生  不需要开启线程
6.setFocusable   为  false 不可聚焦  listview的item可以选中

下面详细介绍:
第一点:
布局文件中,listview控件的高度一定不能使wrap_content
如果是的话会重复调用测量高度的方法
1.listView高度为match_parent
2.高度改为xxxdp.

第二点:
convertView用上,这个只要有一个不为null之后,其它的都不为null.
通过xml转换得到的view对象。
减少填充的调用次数。现在在一个常数集。
1.先写一个适配器
2.里面定义一个list,然后new,实例化
3.先一个追加的方法,可以追加也可以覆盖,也可以再写一个追加一条的方法。


第三点:
减少findViewById的时间,
用法:(1)通过外面定义一个类,里面声明item布局的那些控件。
(1)通过外面定义一个类,里面声明要找的控件的对象
private class ViewHolder {
public int position;
// 这个postiton代表真实的第几条数据如果一页10个,从0-9那下一页就是从10-18。
public TextView title;
public ImageView thumbnail;
}
(2)getview方法中,在convertview==null的条件中,生成viewHolder对象,把得到的控件对象,赋值给viewHolder的里面声明的属性,并把viewHolder作为tag属性赋值给view.即view.setTag(vh);

以上三点的代码如下:

private class MyAdapter extends BaseAdapter {

		private List datas;

		public MyAdapter() {
			datas = new ArrayList();
		}

		public void addAll(List data, boolean clear) {
			if (data != null) {
				if (clear) {
					datas.clear();
				}
				datas.addAll(data);
			}
		}

		public void add(String data) {
			datas.add(data);
		}

		@Override
		public int getCount() {
			return datas.size();
		}

		@Override
		public String getItem(int position) {
			return datas.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				v = LayoutInflater.from(getApplicationContext()).inflate(
						R.layout.item, parent, false);
				ViewHolder vh = new ViewHolder();
				vh.title = (TextView) v.findViewById(R.id.title);
				vh.thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
				v.setTag(vh);

				v.findViewById(R.id.btn).setFocusable(false);
			}

			ViewHolder vh = (ViewHolder) v.getTag();
			vh.position = position;

			String titleStr = getItem(position);

			vh.title.setText(titleStr);

			// 5.列表在甩动时,不用启动线程下载图片
			if (!isFling) {
				// new LoadImgTask(vh, position).equals("http://.....");
			}

			return v;
		}
	}




第四点:
错位
return之前设置好布局就不会错位,如果return之后才尝试设置布局。就会错位。
1.异步
2.如果listView保持静止。就不会错位。
利用position防止错位
每次看看现在的postion和构造时提供的位置是否相等,如果相等,就表示没变过。或者变了又回来了。则设置,否则不设置。
实现方法就是,异步下载图片的时候传一个当前的position,然后把这个值赋给异步里的一个属性,然后当下载完成的时候判断当前viewHolder的positon是不是跟你传入的position相等,如果相等表示是这个位置,就更新ui,否则不更新ui。
代码段:
// 异步下载图片
	private class LoadImgTask extends AsyncTask {
		private String url;
		private ViewHolder vh;
		private final int position;

		// 4.利用position来防止错位
		public LoadImgTask(ViewHolder vh, int position) {
			this.vh = vh;
			this.position = position;
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			url = params[0];
			// TODO downloading这里进行图片下载功能。
			byte[] data = null;
			// 返回解码后的bitmap
			return BitmapFactory.decodeByteArray(data, 0, data.length);
		}

		// 这个方法是下载完成后调用。
		@Override
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);

			if (result != null) {
				// 这个position是开启线程的时候调用的position。这个vh是下载完成后vh的position,
				// 因为vh是外部类的所有他的属性时刻变化着,当你调用的时候外面变动了,引用这个
				// 对象的position也是现在的值。
				if (position == vh.position) {
					// 更新ui
					vh.thumbnail.setImageBitmap(result);
				}
			}
		}
	}


第五点:
如果一下子从1滑到了最后,则这个是不需要起线程的,因为线程池里面的有限。所以抓住此状态。fling甩。设置监听setonScrollListener。
1.判断如果是甩动的状态,就不起线程。
isFling=(scrollState == OnScrollListener.SCROLL_STATE_FLING)
用法:
(1).给listView设置监听
定义标志位
private boolean isFling;
		lv.setOnScrollListener(new OnScrollListener() {
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				// TODO Auto-generated method stub
				isFling = (scrollState == OnScrollListener.SCROLL_STATE_FLING);
			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				// TODO Auto-generated method stub
			}
		});
(2)	// 5.列表在甩动时,不用启动线程下载图片,判断如果没有甩动就开现场下载
			if (!isFling) {
				// 异步开启线程下载,构造里面传入vh,和position。
				// new LoadImgTask(vh, position).equals("http://.....");
			}


第六点:
listView放到了scrollView里面怎么滑动。
listView放了viewPager怎么滑动。
item里面放了button或者checkbox,则整个item不能点击了。
4.4已经修复了此bug.

为什么item不可点,是因为item里面的控件有可聚焦事件,所以外面的
item无法点击。我们可以让那些可聚焦的控件setFocusable(false)...(不可聚焦)
用法:item能实现点击的原理是:除了某个条件还有一个就是里面的控件不聚焦。
(1)例如item里面有button按钮,让控件不聚焦,
// 这是是防止让item里面的控件不聚焦。
v.findViewById(R.id.btn).setFocusable(false);

代码下载地址如下:
http://download.csdn.net/detail/liu13722785488/7840115

你可能感兴趣的:(android基础,安卓高级部分)