ListView的优化(一)
接下来的几章我将主要讲一下关于ListView的优化,尽管如今更多的是recyclerview,但是ListView的使用还是很多的,毕竟是老大哥,接下来直奔主题。
首先,来看一下未优化 之前的Listview的使用,代码贴上。
public class ListViewAdapter extends BaseAdapter { private List<String> mData; private Context context; private LayoutInflater mInflater; public ListViewAdapter(Context context,List<String> mData){ this.context = context; this.mData = mData; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public Object getItem(int i) { return mData.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { view = mInflater.inflate(R.layout.item,null); TextView tv = view.findViewById(R.id.item_tv); ImageView img = view.findViewById(R.id.item_img); tv.setText(mData.get(i)); return view; } }
这里主要分析
public View getView(int i, View view, ViewGroup viewGroup)
该方法主要是用于获取对应位置i的组件,并设置组件数据。但是在每一个位置i获取对应位置组件是都会调用getView()方法,也就意味着每次都会实例化一个view对象,这个view对象也就是我们listView的每一个item对用的组件(在这里也就是item.xml布局文件中对用的父组件),而这个viw在每次调用getView()时都会实例化一次,同时View这个父组件中的TextView和ImageView每次也重新实例化一个对象。
这样在item数目较多时就会创建很多个view,因此效率很低。
而由于每一个item对应的组件其实都是一样的,都是一个TextView和ImageView,因此如果我们可以重复利用这些已经实例化的组件,就可以少创建很多对象,效率自然 也就提高了。
具体如下:
public class ListViewAdapter extends BaseAdapter { private List<String> mData; private Context context; private LayoutInflater mInflater; public ListViewAdapter(Context context,List<String> mData){ this.context = context; this.mData = mData; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public Object getItem(int i) { return mData.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder holder = null; if(view==null){ holder = new ViewHolder();
ViewHolder holder = null; if(view==null){ holder = new ViewHolder(); view = mInflater.inflate(R.layout.item,null); holder.txt = view.findViewById(R.id.item_tv); holder.img = view.findViewById(R.id.item_img); view.setTag(holder); }else { holder = (ViewHolder) view.getTag(); } holder.txt.setText(mData.get(i)); return view;holder.txt = view.findViewById(R.id.item_tv); holder.img = view.findViewById(R.id.item_img); view.setTag(holder); }else { holder = (ViewHolder) view.getTag(); } holder.txt.setText(mData.get(i)); return view; } private class ViewHolder{ public ImageView img; public TextView txt; }}
这里我们创建一个ViewHolder类,ViewHolder并不是Android的API,而是Android Demo中示范代码,通过定义一个ViewHolder来包含每一个item中的所有组件,在ViewHolde定义了item中的组件,在ViewHolder中保存着所有组件的引用,再通过setTag()将这个ViewHolder附加在view上,如下在getView()方法中
ViewHolder holder = null;
if(view==null){ holder = new ViewHolder(); view = mInflater.inflate(R.layout.item,null); holder.txt = view.findViewById(R.id.item_tv); holder.img = view.findViewById(R.id.item_img); view.setTag(holder); }else { holder = (ViewHolder) view.getTag(); } holder.txt.setText(mData.get(i)); return view;
通过判断view是否等于null,如果等于null,那么表示这个view不存在,则创建view,并根据view来执行findViewById()实例化ViewHolder中的TextView和ImageView,在首次实例化View后,设置view.setTag(),将带有子组件引用的ViewHolder附加到View上,从而达到一个视图缓存的目的。这样在下次加载时直接调用getTag()即可取出对应的组件,从而避免多次实例化白白浪费内存。