[转载][Android]ListView性能优化之视图缓存(续) – 农民伯伯 – 博客园.
前言
在上一篇ListView性能优化之视图缓存我们讨论了Google I/O中的优化方法,在各个论坛发帖后得到了不错的反馈,诸如:使用ViewHolder技术Tag的问题,利用HashMap自行存储的方案等。这里结合新浪微博中主界面的做法及测试数据与大家进一步探讨。
文章
[Android]ListView性能优化之视图缓存 [本文的上篇]
[Android]ListView性能优化之视图缓存 [JavaEye讨论帖]
正文
一、新浪微博
1.1 截图
(来自网络)
1.2 反编译后相关代码
public View getView(int paramInt, View paramView, ViewGroup paramViewGroup) { int i = --paramInt; int j = -1; if (i == j); for (Object localObject1 = HomeListActivity.this.getReloadView(); ; localObject1 = HomeListActivity.this.getLoadMoreView()) { label26: return localObject1; int k = HomeListActivity.this.mList.size(); int l = paramInt; int i1 = k; if (l != i1) break; } boolean bool1 = true; boolean bool2 = null; String str1; label110: Object localObject2; if (StaticInfo.mUser == null) { List localList1 = HomeListActivity.this.mList; int i2 = paramInt; str1 = ((MBlog)localList1.get(i2)).uid; List localList2 = HomeListActivity.this.mList; int i3 = paramInt; String str2 = ((MBlog)localList2.get(i3)).uid; String str3 = str1; if (!str2.equals(str3)) break label271; int i4 = 1; label156: if (paramView != null) break label277; HomeListActivity localHomeListActivity1 = HomeListActivity.this; ListView localListView1 = HomeListActivity.this.mLvHome; List localList3 = HomeListActivity.this.mList; int i5 = paramInt; MBlog localMBlog1 = (MBlog)localList3.get(i5); HomeListActivity localHomeListActivity2 = HomeListActivity.this; int i6 = paramInt; boolean bool4 = localHomeListActivity2.isNewCommer(i6); int i7 = HomeListActivity.this.mReadMode; localObject2 = new MBlogListItemView(localHomeListActivity1, localListView1, localMBlog1, bool1, bool2, i4, bool4, i7); } while (true) { localObject1 = localObject2; break label26: str1 = StaticInfo.mUser.uid; break label110: label271: boolean bool3 = null; break label156: label277: localObject2 = paramView; try { MainListItemView localMainListItemView = (MainListItemView)localObject2; List localList4 = HomeListActivity.this.mList; int i8 = paramInt; Object localObject3 = localList4.get(i8); HomeListActivity localHomeListActivity3 = HomeListActivity.this; int i9 = paramInt; boolean bool5 = localHomeListActivity3.isNewCommer(i9); int i10 = HomeListActivity.this.mReadMode; boolean bool6 = bool1; boolean bool7 = bool2; localMainListItemView.update(localObject3, bool6, bool7, bool5, i10); } catch (Exception localException) { HomeListActivity localHomeListActivity4 = HomeListActivity.this; ListView localListView2 = HomeListActivity.this.mLvHome; List localList5 = HomeListActivity.this.mList; int i11 = paramInt; MBlog localMBlog2 = (MBlog)localList5.get(i11); HomeListActivity localHomeListActivity5 = HomeListActivity.this; int i12 = paramInt; boolean bool8 = localHomeListActivity5.isNewCommer(i12); int i13 = HomeListActivity.this.mReadMode; localObject2 = new MBlogListItemView(localHomeListActivity4, localListView2, localMBlog2, bool1, bool2, bool3, bool8, i13); } } }
代码说明:
代码流程已经比较混乱,但是这里能看到并没有直接的inflate,而是自定义了继承自LinearLayout的MBlogListItemView。
public MBlogListItemView(Context paramContext, ListView paramListView, MBlog paramMBlog, boolean paramBoolean1, boolean paramBoolean2, boolean paramBoolean3, boolean paramBoolean4, int paramInt) { super(paramContext); this.context = paramContext; this.parent = paramListView; this.mBlog = paramMBlog; String str1 = paramContext.getCacheDir().getAbsolutePath(); this.mCacheDir = str1; String str2 = paramContext.getFilesDir().getAbsolutePath(); this.mFileDir = str2; ((LayoutInflater)paramContext.getSystemService("layout_inflater")).inflate(2130903061, this); TextView localTextView1 = (TextView)findViewById(2131624016); this.mName = localTextView1; TextView localTextView2 = (TextView)findViewById(2131624041); this.mDate = localTextView2; TextView localTextView3 = (TextView)findViewById(2131624018); this.mContent = localTextView3; TextView localTextView4 = (TextView)findViewById(2131624046); this.mSubContent = localTextView4; ImageView localImageView1 = (ImageView)findViewById(2131624040); this.mIconV = localImageView1; ImageView localImageView2 = (ImageView)findViewById(2131624042); this.mIconPic = localImageView2; ImageView localImageView3 = (ImageView)findViewById(2131624044); this.mUploadPic1 = localImageView3; ImageView localImageView4 = (ImageView)findViewById(2131623979); this.mUploadPic2 = localImageView4; TextView localTextView5 = (TextView)findViewById(2131624047); this.tvForm = localTextView5; TextView localTextView6 = (TextView)findViewById(2131623989); this.tvComment = localTextView6; this.tvComment.setOnClickListener(this); TextView localTextView7 = (TextView)findViewById(2131623988); this.tvRedirect = localTextView7; this.tvRedirect.setOnClickListener(this); ImageView localImageView5 = (ImageView)findViewById(2131624049); this.imComment = localImageView5; this.imComment.setOnClickListener(this); ImageView localImageView6 = (ImageView)findViewById(2131624048); this.imRedirect = localImageView6; this.imRedirect.setOnClickListener(this); ImageView localImageView7 = (ImageView)findViewById(2131624043); this.imGpsIcon = localImageView7; ImageView localImageView8 = (ImageView)findViewById(2131624013); this.mPortrait = localImageView8; LinearLayout localLinearLayout = (LinearLayout)findViewById(2131624045); this.mSubLayout = localLinearLayout; this.mReadMode = paramInt; MBlogListItemView localMBlogListItemView = this; MBlog localMBlog = paramMBlog; boolean bool1 = paramBoolean1; boolean bool2 = paramBoolean2; boolean bool3 = paramBoolean4; int i = paramInt; localMBlogListItemView.update(localMBlog, bool1, bool2, bool3, i); this.mUploadPic1.setOnClickListener(this); this.mUploadPic2.setOnClickListener(this); }
代码说明:
a). MBlogListItemView extends LinearLayout implements MainListItemView
b). inflate(2130903061,this)这个数字代表R.layout.itemview。
二、测试方案(方案五)
按照新浪微博类似的做法进行测试。
2.1 测试代码
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 开始计时
long startTime = System.nanoTime();
TestItemLayout item;
if (convertView == null) {
item = new TestItemLayout(BaseAdapterActivity.this);
} else
item = (TestItemLayout) convertView;
item.icon1.setImageResource(R.drawable.icon);
item.text1.setText(mData[position]);
item.icon2.setImageResource(R.drawable.icon);
item.text2.setText(mData[position]);
// 停止计时
long endTime = System.nanoTime();
// 计算耗时
long val = (endTime – startTime) / 1000L;
Log.e(“Test”, “Position:” + position + “:” + val);
if (count < 100) {
if (val < 2000L) {
sum += val;
count++;
}
} else
mTV.setText(String.valueOf(sum / 100L) + ":" + nullcount);// 显示统计结果
return item;
}
[/java]
TestItemLayout
[java]
public class TestItemLayout extends LinearLayout {
public TextView text1;
public ImageView icon1;
public TextView text2;
public ImageView icon2;
public TestItemLayout(Context context) {
super(context);
((LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.list_item_icon_text, this);
icon1 = (ImageView) findViewById(R.id.icon1);
text1 = (TextView) findViewById(R.id.text1);
icon2 = (ImageView) findViewById(R.id.icon2);
text2 = (TextView) findViewById(R.id.text2);
}
}
[/java]
2.2 测试结果
次数 | 4个子元素 | 10个子元素 |
第一次 | 347 | 460 |
第二次 | 310 | 477 |
第三次 | 324 | 508 |
第四次 | 339 | 492 |
第五次 | 341 | 465 |
三、总结
从测试结果来看与ViewHolder性能非常接近,不会出现tag图片变小的问题(关于图片变小的问题,有朋友说是TAG中的元素对大小和位置有记忆),也能有效的减少findViewById的执行次数,这里建议完全可以取代ViewHolder。
关于ListView内部Adapter的心得大家可以看一下上文的总结4.1。
四、考虑
关于静态内部类这里不是很理解,是否能应用方案五还有待验证。
结束
优化ListView不仅仅只有对convertView的优化,还有许多这样那样的技巧,欢迎大家交流与分享 🙂