原文地址:http://android.xsoftlab.net/training/improving-layouts/smooth-scrolling.html
想要讓ListView滑動流暢的關鍵所在是減輕主線程的負擔。要確保任何的磁盤訪問、網絡訪問、或SQL訪問都是在單獨的線程中履行的。如果要測試APP的狀態,可以開啟StrictMode。
使用工作線程可使UI線程將所有的注意力都集中在UI的繪制上。在很多情況下,使用AsyncTask所提供的功能就能夠在工作線程中處理耗時任務。AsyncTask會自動的將execute()發起的要求排隊,并順次履行。這意味著你不要自己創建線程池。
在下面的示例代碼中,AsyncTask被用來加載1張圖象,并在加載結束后自動的將其渲染到UI上。它還在圖象加載時展現了1個旋轉的進度條。
// Using an AsyncTask to load the slow images in a background thread
new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder v;
@Override
protected Bitmap doInBackground(ViewHolder... params) {
v = params[0];
return mFakeImageLoader.getImage();
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if (v.position == position) {
// If this item hasn't been recycled already, hide the
// progress and set and show the image
v.progress.setVisibility(View.GONE);
v.icon.setVisibility(View.VISIBLE);
v.icon.setImageBitmap(result);
}
}
}.execute(holder);
從Android 3.0開始,AsyncTask提供了1項新特性:可以將任務運行在多核處理器上。你可使用executeOnExecutor()方法發起履行要求,這樣多個要求就能夠同時進行,同時進行的任務數量取決于CPU的核心數量。
在滑動ListView時,代碼可能會頻繁的調用findViewById(),這會下降性能。就算是Adapter將已加載過的View返回,但是在復用時還是需要去查詢這些View來更新它們。杜絕重復使用findViewById()的方法就是使用”View Holder”設計模式。
ViewHolder對象將每一個View組件存儲于布局容器的tag屬性內,所以你可以快速訪問它們而不需要每次都去查詢。首先,你需要創建1個類來持有已加載的View:
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
然后對ViewHolder的成員屬性賦值,然后將其寄存在布局容器內:
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);
那末現在就能夠很方便的對這些View組件進行訪問,而不再需要對它們單獨進行查詢,如此即可以節省出寶貴的CPU資源。