ListView優化一直是一個老生常談的問題。無論是面試還是尋常的開發中,ListView永遠不會被忽略掉,那么這篇文章我們來看看怎樣最大化的優化ListView的性能。
- 1.在adapter中的getView方法中盡量少使用邏輯
- 2.盡最大可能避免GC
- 3.滑動的時候不載入圖片
- 4.將ListView的scrollingCache和animateCache設置為false
- 5.item的布局層級越燒越好
- 6.使用ViewHolder
1.在adapter中的getView方法中盡量少使用邏輯
不要在你的getView()中寫過多的邏輯代碼,我們能夠將這些代碼放在別的地方。比如:
優化前的getView():
@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
Object current_event = mObjects.get(position);
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.row_event, null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//在這里進行邏輯推斷。這是有問題的
if (doesSomeComplexChecking()) {
holder.ThreeDimention.setVisibility(View.VISIBLE);
} else {
holder.ThreeDimention.setVisibility(View.GONE);
}
// 這是設置image的參數,每次getView方法運行時都會運行這段代碼。這顯然是有問題的
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams);
return convertView;
}
優化后的getView():
@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
Object object = mObjects.get(position);
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.row_event, null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
//設置參數提到這里,僅僅有第一次的時候會運行,之后會復用
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// 我們直接通過對象的getter方法取代剛才那些邏輯推斷。那些邏輯推斷放到別的地方去運行了
holder.ThreeDimension.setVisibility(object.getVisibility());
return convertView;
}
2.GC 垃圾回收器
當你創建了大量的對象的時候。GC就會頻繁的運行。所以在getView()方法中不要創建非常多的對象。最好的優化是,不要在ViewHolder以外創建不論什么對象。假設你的你的log里面發現“GC has freed some memory”頻繁出現的話。那你的程序肯定有問題了。
你能夠檢查一下:
a) item布局的層級是否太深
b) getView()方法中是否有大量對象存在
c) ListView的布局屬性
3.載入圖片
假設你的ListView中須要顯示從網絡上下載的圖片的話。我們不要在ListView滑動的時候載入圖片,那樣會使ListView變得卡頓,所以我們須要再監聽器里面監聽ListView的狀態。假設滑動的時候,停止載入圖片,假設沒有滑動,則開始載入圖片
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
//停止載入圖片
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
imageLoader.stopProcessingQueue();
} else {
//開始載入圖片
imageLoader.startProcessingQueue();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
4.將ListView的scrollingCache和animateCache設置為false
scrollingCache: scrollingCache本質上是drawing cache,你能夠讓一個View將他自己的drawing保存在cache中(保存為一個bitmap),這樣下次再顯示View的時候就不用重畫了,而是從cache中取出。默認情況下drawing cahce是禁用的。由於它太耗內存了,可是它確實比重畫來的更加平滑。
而在ListView中,scrollingCache是默認開啟的,我們能夠手動將它關閉。
animateCache: ListView默認開啟了animateCache,這會消耗大量的內存,因此會頻繁調用GC,我們能夠手動將它關閉掉
優化前的ListView
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:smoothScrollbar="true"
android:visibility="gone" />
優化后的ListView
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:scrollingCache="false"
android:animationCache="false"
android:smoothScrollbar="true"
android:visibility="gone" />
5.降低item的布局的深度
我們應該盡量降低item布局深度,由於當滑動ListView的時候,這回直接導致測量與繪制,因此會浪費大量的時間。所以我們應該將一些不必要的布局嵌套關系去掉。降低item布局深度
6.使用ViewHolder
這個大家應該非常熟悉了,可是不要小看這個ViewHolder,它能夠大大提高我們ListView的性能
ListView的優化我們已經講完了。假設在你的項目中。這些基本優化你還沒有做到的話。那么你的ListView是有問題的,還有非常大的提升潛力。以后再使用ListView的時候,一定要將這幾點考慮進去,發揮它的最大的性能。
