前言緩存
在上一篇ListView性能優化之視圖緩存咱們討論了Google I/O中的優化方法,在各個論壇發帖後獲得了不錯的反饋,諸如:使用ViewHolder技術Tag的問題,利用HashMap自行存儲的方案等。這裏結合新浪微博中主界面的作法及測試數據與你們進一步探討。
性能優化
文章優化
[Android]ListView性能優化之視圖緩存 [本文的上篇]
ui
[Android]ListView性能優化之視圖緩存 [JavaEye討論帖]
this
正文spa
1、新浪微博code
1.1 截圖
1.2 反編譯後相關代碼
HomeListActivity
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。
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、測試方案(方案五)
按照新浪微博相似的作法進行測試。
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;
}
TestItemLayout
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);
}
}
2.2 測試結果
次數 |
4個子元素 |
10個子元素 |
第一次 |
347 |
460 |
第二次 |
310 |
477 |
第三次 |
324 |
508 |
第四次 |
339 |
492 |
第五次 |
341 |
465 |
3、總結
從測試結果來看與ViewHolder性能很是接近,不會出現tag圖片變小的問題(關於圖片變小的問題,有朋友說是TAG中的元素對大小和位置有記憶),也能有效的減小findViewById的執行次數,這裏建議徹底能夠取代ViewHolder。
關於ListView內部Adapter的心得你們能夠看一下上文的總結4.1。
4、考慮
關於靜態內部類這裏不是很理解,是否能應用方案五還有待驗證。
5、後期維護
2011-4-29 來自Stony Wang關於Tag的解釋:
結束
優化ListView不單單隻有對convertView的優化,還有許多這樣那樣的技巧,歡迎你們交流與分享 :)