请描述baseadapter优化策略,为什么要这样

 我来答
huanglenzhi
2016-03-07 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
采纳数:117538 获赞数:517191
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。

向TA提问 私信TA
展开全部
  在BaseAdapter中,这个抽象方法非常重要,它就是根据position的值返回对象的数据项的View视图,所以我们主要也是围绕这个方法来达到效率上优化的目的。
public View getView(int position, View convertView, ViewGroup parent) { return null; }
  简单介绍一下这个函数的参数,position是ID索引值,也就是ListView的对应的数据项的序号,而convertView则是View视图复用的基础,如果为第一个页面的数据,它的值为null,所以我们可以根据convertView的值来决定我们是否要new一个View的实例出来。
参见下面代码
1 @Override
2 public View getView(int position, View convertView, ViewGroup parent) {
3   if(convertView == null){
4     convertView = new TextView(context);//新建一个字符串控件
5     ((TextView)convertView).setText(position);//实现其是第几个数据项
6   }
7   else{
8     ((TextView)convertView).setText(position);//重新修改其是第几个数据项
9   }
10   return convertView;
11 }

  为了简单起来,我这里的View只是一个简简单单的字符串控件,在代码中我们可以看到,先对convertView进行判断,如果其值为null,则说明该方法此时返回的View是第一页的视图,所以需要new出一个View的实例,然后对其进行设置显示的内容并返回(这里设置的内容为position)。如果其值不为null,则说明此时的View视图是可以复用其他已经隐藏的View实例,而convertView的索引就是这个隐藏的实例,自然我们不用重新创建一个新的View实例而直接对convertView进行重新设置数值并返回便可。
  这样就保证了程序里面只有足够界面显示的View实例的个数存在,而不会有多余的View来占用系统资源,由此也提高了一点点效率。
  这是BaseAdapter的效率优化的一个方面,接下来我们还要说一下另外一个方面,说明白了也就是一个小技巧来提高效率。对于一个BaseAdapter来说,显示的界面肯定不是仅仅的一两个字符串控件(不然我们就用ArrayAdapter了多简便),而一般是加载一个根据layout生成的布局控件,相对来说这个的布局控件会比较复杂,我们会对其的子控件进行获取并赋值返回,所以我们经常要调用findViewById()这个方法来或者子控件的引用。而findViewById()会比较消耗系统资源,频繁的调用在我们快速滑动界面时会加重手机的负担,所以我们也可以对这个地方进行一些小小的改进。
参考这个代码
1 public class PersonAdapter extends BaseAdapter {
2 private List<Person> persons;//绑定的数据
3 private int resource;//绑定的Layout数据项界面
4 private LayoutInflater inflater;//布局填充服务
5
6 public PersonAdapter(Context context, List<Person> persons, int resource) {
7 this.persons = persons;
8 this.resource = resource;
9 inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
10 }
11 @Override
12 public int getCount() {
13 return persons.size();
14 }
15 @Override
16 public Object getItem(int position) {
17 return persons.get(position);
18 }
19 @Override
20 public long getItemId(int position) {
21 return position;
22 }
23 @Override
24 public View getView(int position, View convertView, ViewGroup parent) {
25 TextView nameView = null;
26 TextView phoneView = null;
27 if(convertView == null){
28 convertView = inflater.inflate(resource, null);//生成绑定数据的View界面
29 nameView = (TextView) convertView.findViewById(R.id.name);
30 phoneView = (TextView) convertView.findViewById(R.id.phone);
31
32 ViewCache cache = new ViewCache();
33 cache.nameView = nameView;
34 cache.phoneView = phoneView;
35 convertView.setTag(cache);
36 }else{
37 ViewCache cache = (ViewCache) convertView.getTag();
38 nameView = cache.nameView;
39 phoneView = cache.phoneView;
40 }
41 Person person = persons.get(position);
42 //下面代码实现数据绑定
43 nameView.setText(person.getName());
44 phoneView.setText(person.getPhone());
45
46 return convertView;
47 }
48 /**
49 *保存findViewById获得的子控件索引的内部类
50 */
51 private final class ViewCache{
52 public TextView nameView;
53 public TextView phoneView;
54 }
55 }新窗口

  重点还是放在getView()这个方法上。在代码里面,我写了一个ViewCache的私有内部类,主要用来保存要来复用的View所需要获得的子控件的索引值。稍微解释一下代码,如果convertView为null,则说明需要new出一个View实例,在这里就是调用Inflater这个系统服务根据resource这个界面的ID值来生成一个View实例,然后用findViewById这个方法来或者其中的子控件的值,并保存在内部类ViewCache中,放入Tag中,setTag(object)是可以放入一个任意的类来保存成为缓存,因为其是Object。最后设置View子控件的内容并返回。如果不为null呢,现在则需要重用View实例了,所以我们也顺带重用一下保存在Tag里面的ViewCache的类成员变量的子控件索引值,而不需要重新去一个一个调用findViewById()这个方法,在界面足够复杂时这样是可以节省很多系统资源的。
  这就是BaseAdapter提高效率的两种小技巧,如果大牛有其他更好的技巧,也希望能分享分享用来学习一下。
  另外也说一下SimplerAdapter使用遇到的一个小问题,当然也是对于新手来说的。就是关于调用notifyDataSetChanged()但是List里面的数据不更改的问题,其实也就是你的数据源更改出错了,例如下面代码它是不会改变数据的。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式