1、爲什麼做優化
說起爲什麼要對ListView這個控件做優化,這個問題還真不是那麼容易回答,因爲它要優化的原因實在是太簡單,那就是Android手機性能有限,要讓它跑起來很流暢,自然就有了優化的需求了。優化過後的應用程序,會跑得比較流暢,能夠讓用戶體驗顯著提升。
這裏我們主要討論它需要節約時間,讓程序更加流暢。那麼問題來了,如何節約時間了,這就是一個空間換時間的問題了。
2、ListView工作原理
如果要談優化,首先應該對ListView這個控件怎麼運行的瞭解清楚吧,這個東西不瞭解,我們談優化猶如水中撈月一樣,是個笑話。
ListView其實是一個滑動控件,只是使用的是list集合存儲數據,顯示的方式是一個條目佔滿一行這樣的形式來的。與之類似的GrivdView也是類似的工作原理,一通則百通,類似的道理。ListView是一堆具有相同屬性的數據,展示在界面上。什麼是有規律的呢?比如,食堂的一排桌子椅子,他們就是又規律的放在一起的,只是每個桌子上坐着的人可能不一樣。如果我們把人看作數據,那麼桌子和椅子就可以看作是我們界面上的控件。
基於上面的認識,我們會不會想到,如果是這樣的話,我們只要獲取到不同的數據,然後將控件複製多個就可以了,對不對?嗯,就是這樣的,我們看一下下面的圖示:
上面這幅圖,是我從網上找來的,比我畫得好,我就不重複造輪子了。這裏有兩個意思,第一個是重複創建很多個item控件,第二個是,利用相同的item控件。第一個我們上面已經解說了,這裏不再贅述,我們談談第二個。這裏我們發現一個問題,那就是我們的手機屏幕大小是有限的,但是item的數據內容可能就會有很多,不只是幾條數據,幾十條數據,可能成百上千條數據。那麼,android系統中如何做優化的呢?
原始的方式,我們只顯示這麼多控件信息,控件保持不變,變化的是數據,使用相同的控件信息,但是使用不同的數據內容。哇靠,清晰了吧!
3、簡單優化方式
最簡單的方式是使用conentView進行緩存處理,這裏代碼如下:
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item_more_view, null);
holder.tv_item_title = (TextView) convertView
.findViewById(R.id.tv_item_more_title);
holder.iv_item_home = (ImageView) convertView
.findViewById(R.id.iv_item_more_view);
holder.tv_item_issue = (TextView) convertView
.findViewById(R.id.tv_item_more_issue);
holder.progressBar = (ProgressBar) convertView
.findViewById(R.id.bar_item_more);
holder.tv_item_person = (TextView) convertView
.findViewById(R.id.tv_person_item_more);
holder.btn_item_home = (Button) convertView
.findViewById(R.id.btn_item_more);
}
4、深度優化方式
經過簡單的測試,上面的代碼,大概能優化50%左右,但是我們發現,這種優化方式還不夠,視圖的回收並不是我們所期望的最好方式,這裏我們可以把它再次緩存起來。說到底,還是一個空間換時間的思路:
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item_more_view, null);
holder.tv_item_title = (TextView) convertView
.findViewById(R.id.tv_item_more_title);
holder.iv_item_home = (ImageView) convertView
.findViewById(R.id.iv_item_more_view);
holder.tv_item_issue = (TextView) convertView
.findViewById(R.id.tv_item_more_issue);
holder.progressBar = (ProgressBar) convertView
.findViewById(R.id.bar_item_more);
holder.tv_item_person = (TextView) convertView
.findViewById(R.id.tv_person_item_more);
holder.btn_item_home = (Button) convertView
.findViewById(R.id.btn_item_more);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
這裏的ViewHolder如下所示:
/** 界面控件 */
public final class ViewHolder {
public TextView tv_item_title; // 標題欄
public ImageView iv_item_home; // 商品圖片
public TextView tv_item_issue;// 顯示第幾期
public ProgressBar progressBar;// 進度條
public TextView tv_item_person;// 顯示還有多少人
public Button btn_item_home;// 搶單按鈕
}
5、優化總結
(1)、減少findViewById()的次數,findViewById是一個相對比較耗性能的操作,它每次都需要到佈局文件中去查找空間信息,然後加載bean對象中的數據內容,顯示在界面上。
(2)、優化,其實也就是兩種,一種是時間換空間,一種空間換時間。依照現在對用戶體驗的重視,硬件資源的價格下降,大多數情況都是使用空間換時間,要讓用戶體驗更好。
(3)、緩存,優化要尤其注意緩存這個東西,它的優化是最快的。重新在內存中生成的時間遠大於直接從內存中獲取,最常見的就是數據庫的鏈接,不要經常斷開去查詢,這樣做是非常耗時的操作。
(4)、經驗,在做優化的時候,經驗也是很重要的,不過這一點在移動端並不是那麼明顯。在做服務器端開發的時候,這種經驗就非常重要,你對一個業務的熟悉,有助於你寫出更好的程序。優化並不僅僅是從程序代碼中優化,也可以從業務流程上去優化。