- 前言
上周五(3.24)收到阿里的电话,(离一面刚好过去一周),面试的过程首先从项目开始,说到了评价列表,就问我是不是一个listview。后来就说起了recyclerview和listview的区别。我说了一堆,他说起了itemviewtype,我就补充了listview没有这个属性,他追问了我一下,真的没有嘛?我还自信地说没有,他也没指出,就开始挖了坑自己在里面跳了。
首先,他问我假如叫我设置这么一个itemType的属性,我会怎么会?
我就思索了一下,回答说提供一个带一个int值的接口,adapter实现这个接口在getView方法根据不同的int值加载不同的item布局。后来又说convertView的setTag()方法,有没有提供另外一个方法去避免擦除tag值。后来我还犹豫了一下,就说一般我们传入的是this值。他又给我设置了一个情景,假如不同的A和B布局使用不同的item,那么这个tag值你怎么做到避免擦除这个tag,后来我就想到了shareprefence,根据传入不同的int值,去保存不同的tag,但取值的时候也根据这个int值去get。他就说也行。直到今晚,我经过百度,确实发现了这个问题在以前就有提及到了。
比如,QQ信息上不同的信息的来源上的item是不一致的,比如新闻和联系人的消息等等。那么我们setTag()的时候是如何做到避免这个tag擦除的呢?
后来,我在api里面还看到了下面这个方法:
* @see #setTag(Object)
* @see #getTag(int)
*/
public void setTag(int key, final Object tag) {
// If the package id is 0x00 or 0x01, it's either an undefined package
// or a framework id
if ((key >>> 24) < 2) {
throw new IllegalArgumentException("The key must be an application-specific "
+ "resource id.");
}
setKeyedTag(key, tag);
}
我想,他是想我回答使用这个方法吧。当时我也没想到,用得相对比较少。
当我看到这个方法的时候,确实也是豁然大悟。
但是,这里的tag值传入不同的viewholder,但是key又是什么呢?
假如有三个itemType。那么我们这样写:
convertView.setTag(1,viewholder1);
convertView.setTag(2,viewholder2);
convertView.setTag(3,viewholder3);
当我们convertView.getTag(“你所存的key”)时其实会报错的。
public Object getTag(int key) {
if (mKeyedTags != null) return mKeyedTags.get(key);
return null;
}
官方文档对setTag(int key, final Object tag)有这么一个说法:
“The specified key should be an id declared in the resources of the application to ensure it is unique (see the ID resource type). Keys identified as belonging to the Android framework or not associated with any package will cause an IllegalArgumentExceptionto
be thrown.”
IllegalArgumentException 的原因就在于 key 不唯一,那么如何保证这种唯一性呢?
解决如下:
1.res/values/strings.xml 中添加
<resources>
<item type="id" name="tag_first">
</item>
<item type="id" name="tag_second">
</item>
<item type="id" name="tag_third">
</item>
</resources>
2.getView使用如下:
if(convertView==null){
convertView=new ViewHolder();
convertView.setTag(R.id.tag_first,viewholder1);
convertView.setTag(R.id.tag_second,viewholder2);
convertView.setTag(R.id.tag_third,viewholder3);
}
else{
convertView = (ViewHolder) convertView.getTag(R.id.tag_first);
convertView = (ViewHolder) convertView.getTag(R.id.tag_second);
convertView = (ViewHolder) convertView.getTag(R.id.tag_third);
}
至于一些细节的东西我留给读者继续去完善吧。