1. 程式人生 > >Android ListView載入多item佈局及效能優化

Android ListView載入多item佈局及效能優化

前言:在開發過程中,遇到一些比較舊的專案,請求網路資料時,介面返回一長串的JSON字串,其中包括各種不相關的資料。而我們又需要把這些資料一一對應寫在同一個介面上,又需要分別展示在不同的佈局上,這時候就需要用到ListView。

而當listview有大量的資料需要載入的時候,會佔據大量記憶體,影響效能,這時候就需要按需填充並重新使用view來減少物件的建立。所以這裡我們在展示多佈局的同時,也對ListView載入效能優化。

廢話講了這麼多,下面我們直接開始做個類似獲取課程大綱的demo,先看一眼需要做的效果圖介面:

這裡寫圖片描述

需求是,B資料量會根據請求的資料而發生變化,A,B,C分別對應不同的佈局。

下面直接上程式碼:

package com.donkor.demo;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
import java.util.Map;

/**
 * @author
donkor */
public class DetailListAdapter extends BaseAdapter { private Activity mContext; //執行上下文 private List<Map<String, Object>> listItems; //列表資訊集合 private LayoutInflater inflater; //檢視容器 final int TYPE_1 = 0; final int TYPE_2 = 1; final
int TYPE_3 = 2; public DetailListAdapter(Activity context, List<Map<String, Object>> listItems) { this.mContext = context; //建立檢視容器並設定上下文 inflater = LayoutInflater.from(context); this.listItems = listItems; } @Override public int getCount() { return listItems.size(); } @Override public Object getItem(int position) { return listItems.get(position); } @Override public long getItemId(int position) { return 0; } /** * 根據資料列表的position返回需要展示的layout的對應的type * type的值必須從0開始 */ @Override public int getItemViewType(int position) { int p = position; //這裡我們修改的是對應頭item和底部item if (p == 0) return TYPE_1; else if (p == (listItems.size()-1)) return TYPE_3; else return TYPE_2; } /** * 該方法返回多少個不同的佈局 */ @Override public int getViewTypeCount() { return 3; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder1 holder1 = null; ViewHolder2 holder2 = null; ViewHolder3 holder3 = null; int type = getItemViewType(position); if (convertView == null) { inflater = LayoutInflater.from(mContext); // 按當前所需的樣式,確定new的佈局 switch (type) { case TYPE_1: convertView = inflater.inflate(R.layout.couese_detail_top, parent, false); holder1 = new ViewHolder1(); holder1.tvCourseTime = (TextView) convertView .findViewById(R.id.tvCourseTime); holder1.tvTeacherName = (TextView) convertView .findViewById(R.id.tvTeacherName); holder1.tvCourseObject = (TextView) convertView .findViewById(R.id.tvCourseObject); convertView.setTag(holder1); break; case TYPE_2: convertView = inflater.inflate(R.layout.course_list_item, parent, false); holder2 = new ViewHolder2(); holder2.tvCoursedescwap = (TextView) convertView .findViewById(R.id.tvCoursedescwap); convertView.setTag(holder2); break; case TYPE_3: convertView = inflater.inflate(R.layout.course_detail_bottom, parent, false); holder3 = new ViewHolder3(); holder3.ivCoursePic = (ImageView) convertView .findViewById(R.id.ivCoursePic); convertView.setTag(holder3); break; default: break; } } else { switch (type) { case TYPE_1: holder1 = (ViewHolder1) convertView.getTag(); break; case TYPE_2: holder2 = (ViewHolder2) convertView.getTag(); break; case TYPE_3: holder3 = (ViewHolder3) convertView.getTag(); break; } } // 設定資源 switch (type) { case TYPE_1: String courseTime = (String) listItems.get(position).get("courseTime"); String teacherName = (String) listItems.get(position).get("teacherName"); String courseObject = (String) listItems.get(position).get("courseObject"); holder1.tvCourseTime.setText(courseTime); holder1.tvTeacherName.setText(teacherName); holder1.tvCourseObject.setText(courseObject); break; case TYPE_2: String author = (String) listItems.get(position).get("author"); holder2.tvCoursedescwap.setText(author); break; case TYPE_3: holder3.ivCoursePic.setImageResource(R.mipmap.background2); break; } return convertView; } public class ViewHolder1 { TextView tvCourseTime, tvTeacherName, tvCourseObject; } public class ViewHolder2 { TextView tvCoursedescwap; } public class ViewHolder3 { ImageView ivCoursePic; } }

※當處理一些耗時的資源載入的時候需要做到以下幾點,以使你的載入更快更平滑

  1. 介面卡在介面主執行緒中進行修改
  2. 可以在任何地方獲取資料但應該在另外一個地方請求資料
  3. 在主介面的執行緒中提交介面卡的變化並呼叫adapter的notifyDataSetChanged()方法修改UI

▲其他需要注意的地方

  • adapter中的getViewTypeCount():該方法返回多少個不同的佈局
  • adapter中的getItemViewType(int
    position):根據資料列表的position返回需要展示的layout的對應的type。 type的值必須從0開始