ListView的优化
来源:互联网 发布:淘宝刷客论坛 编辑:程序博客网 时间:2024/06/16 23:43
前面在说ListView的时候我们说,这是android中一个使用非常广泛的控件,所以呢这里特别想强调一下这个控件的优化问题。
我们说我们在getView()方法中都会执行两个耗时操作:inflate方法获取布局对象,findViewById方法获取控件对象,所以限制这两种方法的使用就能有效提高ListView 的性能。
对于每个新的item的出现就要调用一次getView的方法,所以在实际的操作中,每一次出现手势滑动,就要调用getView的方法。所以我们的解决办法是:对于inflate方法我们使用convertView解决,称为一级优化,findViewById使用ViewHolder解决,称为二级优化,二级优化必须在一级优化的基础上。
使用convertView优化
还是采用前面的代码:
package com.example.dreamcreationman.listview;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import java.util.Map;/** * Created by Dream on 2017/2/21. */public class MyAdapter extends BaseAdapter { List<Map<String,Object>> list; LayoutInflater inflater; public MyAdapter(Context context) { this.inflater=LayoutInflater.from(context); } public void setList(List<Map<String, Object>> list) { this.list = list; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { //未优化代码 View view= inflater.inflate(R.layout.ti,null); if(convertView==null){ convertView=inflater.inflate(R.layout.ti,null); } ImageView logo= (ImageView) convertView.findViewById(R.id.logo); TextView name = (TextView) convertView.findViewById(R.id.name); TextView version = (TextView) convertView.findViewById(R.id.version); TextView size = (TextView) convertView.findViewById(R.id.size); Map map=list.get(position); logo.setImageResource((Integer) map.get("logo")); name.setText((String) map.get("name")); version.setText((String) map.get("version")); size.setText((String) map.get("size")); //修改返回值 return convertView; }}
为什么用了convertView就能够达到优化的效果呢?
android里有一个循环回收器的Recycler,用于回收不显示在屏幕上的View。
第一屏的View渲染当然就不可避免了,但是当遇到手势操作下滑的时候,第一屏原来上方的item就被滑出了屏幕,此时,第一个item就会被回收到Recycler的回收池里,同时新的item也在进行产生,截至到目前,convertView还没发挥作用。然后再往上滑,此时,原来第一个item的回收已经完成,那么该再产生的item就直接使用第一个item的缓存数据,以此类推。也就是说,其实在整个过程中,总共参与了调用反射机制就是第一屏的View加一次,然后就是在循环利用视图缓存。而且这个更好的是再次上滑的时候也是如此。所以这个Recycler回收缓冲池大大减少了inflater的调用(当然·有的item只能显示半个的时候。算作一个,因为此时android也是完全渲染的)。
使用ViewHolder优化
package com.example.dreamcreationman.listview;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import java.util.Map;/** * Created by Dream on 2017/2/21. */public class MyAdapter extends BaseAdapter { List<Map<String,Object>> list; LayoutInflater inflater; public MyAdapter(Context context) { this.inflater=LayoutInflater.from(context); } public void setList(List<Map<String, Object>> list) { this.list = list; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { //View view= inflater.inflate(R.layout.ti,null); ViewHolder holder=null; if(convertView==null){ convertView=inflater.inflate(R.layout.ti,null); holder=new ViewHolder(); holder.logo= (ImageView) convertView.findViewById(R.id.logo); holder.name = (TextView) convertView.findViewById(R.id.name); holder.version = (TextView) convertView.findViewById(R.id.version); holder.size = (TextView) convertView.findViewById(R.id.size); convertView.setTag(holder); }else{ holder= (ViewHolder) convertView.getTag(); } Map map=list.get(position); holder.logo.setImageResource((Integer) map.get("logo")); holder.name.setText((String) map.get("name")); holder.version.setText((String) map.get("version")); holder.size.setText((String) map.get("size")); return convertView; } public static class ViewHolder{ ImageView logo; TextView name; TextView version; TextView size; }}
getTag();存储的是Object对象,所以要强转下类型。
为什么ViewHolder能够进行优化呢?
ViewHolder是一个内部类,这里面存放了我们需要加载的控件对象。同样的第一屏的View渲染不可避免,同时将ViewHolder直接放给convertView,遇到手势操作下滑,第一屏原来上方的item被滑出,下一次直接调用else的方法。然后再往上滑,此时,原来第一个ViewHolder的回收已经完成,当再次使用到convertView时,直接利用ViewHolder来进行。以此类推,就大大减少了findViewById的调用。
但是由于每行的内容都不同,需要每次加载更新,所以下面的内容不能写在if语句里执行。
Map map=list.get(position); holder.logo.setImageResource((Integer) map.get("logo")); holder.name.setText((String) map.get("name")); holder.version.setText((String) map.get("version")); holder.size.setText((String) map.get("size"));
好了,关于ListView的优化的分享就到这。欢迎大家在评论区指出错误与不足之处。
谢谢观看
- ListView的优化
- listView的优化
- ListView的优化
- Listview的优化
- listView的优化
- ListView的优化
- ListView的优化
- listview的优化
- ListView的优化(1)
- ListView的优化(2)
- ListView的优化(3)
- ListView的优化
- listView的优化
- Listview的优化
- 关于listview的优化
- ListView的优化
- ListView的优化
- ListView的优化
- Codeforces768C-Jon Snow and his Favourite Number
- Objective-C使用NSFileHandle类对文件进行基本操作,IOS文件操作
- javaWEB总结(23):HttpSession URL重写
- 《JAVA与模式》之门面模式
- Eclipse恢复默认主题及配色;eclipse-color-theme插件安装
- ListView的优化
- windows平台probuf协议socket通信例子
- vue2.0使用Sortable.js实现的拖拽功能
- KMP算法字符串匹配
- acm训练 2017 02 21
- Redis配置文件
- 多边形Polygon
- Java反射机制
- SystemServer进程源码分析之二