前言
新聞客戶端開發(fā)中肪笋,經(jīng)吃屡看到數(shù)據(jù)流中有很多視圖類型,類型有:新聞藤乙、圖片猜揪、網(wǎng)頁(yè)鏈接、視頻坛梁、視頻+文字而姐、廣告等等,這種情況下處理不好划咐,則會(huì)導(dǎo)致代碼臃腫拴念,App 內(nèi)存占用過高,列表卡頓褐缠。所以非常有必要對(duì)復(fù)雜 listView 進(jìn)行一下優(yōu)化政鼠。
MVP 模式使項(xiàng)目的整體結(jié)構(gòu)更加清晰了,業(yè)務(wù)層队魏、UI層公般、邏輯層進(jìn)行了清晰的劃分,那么實(shí)際項(xiàng)目中使用 MVP 模式后,最后有個(gè)疑問對(duì)于負(fù)責(zé)的 adapter 中該怎么運(yùn)用 MVP 模式進(jìn)行重寫呢官帘?
一瞬雹、沒有運(yùn)用 MVP 實(shí)現(xiàn)復(fù)雜 ListView 適配器
以下代碼是沒有優(yōu)化前的處理,功能簡(jiǎn)單刽虹,不加描述了酗捌,直接上代碼。
注意添加新布局后涌哲,別忘記修改TYPE_COUNT
,否則引起數(shù)組越界異常意敛。
class CustomAdapter extends BaseAdapter {
static final int TYPE_DATA = 0;
static final int TYPE_IMAGE = 1;
static final int TYPE_COUNT = 2;
@Override
public int getCount() {
return null == mArrayList ? 0 : mArrayList.size();
}
@Override
public int getViewTypeCount() {
return TYPE_COUNT;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_IMAGE;
} else {
return TYPE_DATA;
}
}
@Override
public Object getItem(int position) {
return mArrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 1.初始化不同類型布局的控件
final ViewHolder viewHolder;
int type = getItemViewType(position);
if (convertView == null || convertView.getTag() == null) {
viewHolder = new ViewHolder();
switch (type) {
case TYPE_DATA:
convertView = View.inflate(mContext, R.layout.item_text, null);
viewHolder.tv_text = (TextView) convertView.findViewById(R.id.tv_text);
break;
case TYPE_IMAGE:
convertView = View.inflate(mContext, R.layout.item_image, null);
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 2.渲染不同布局類型的數(shù)據(jù)
if (type == TYPE_DATA) {
renderData(viewHolder, position);
}
if (type == TYPE_IMAGE) {
}
return convertView;
}
}
// 抽取渲染不同類型數(shù)據(jù)的方法。防止getView()方法體過于復(fù)雜
private void renderData(ViewHolder viewHolder, int position) {
String title = mArrayList.get(position);
viewHolder.tv_text.setText(title);
}
// 所有類型的布局的控件都包含在內(nèi)
static class ViewHolder {
public TextView tv_text;
public ImageView poster;
}
本代碼實(shí)現(xiàn)方式參考廣告聯(lián)盟demo
二膛虫、使用 MVP 后高效渲染復(fù)雜 listView
每個(gè) item 的數(shù)據(jù)處理是在單獨(dú)一個(gè) ViewHolder 上處理草姻。
所有的 ViewHolder 所在包結(jié)構(gòu)view >>> viewholder
下面。
public class NewsListAdapter extends BaseAdapter {
private static final int TYPE_ONE = 0;
private static final int TYPE_TWO = 1;
private static final int TYPE_THR = 2;
private static final int TYPE_COUNT = 3;
private List<NewEntity> newsList;
...
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
// 1.獲取 item 對(duì)應(yīng)的那組元素
NewEntity entity = newsList.get(position);
// 2. 創(chuàng)建各個(gè) XXHolder 引用稍刀,假設(shè)有3個(gè)視圖分別對(duì)應(yīng)了3個(gè)Holder
OneHolder oneHolder;
TwoHolder twoHolder;
ThrHolder thrHolder;
// 3.
int type = getItemViewType(position);
switch(type) {
case TYPE_ONE:
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.item_one, null);
oneHolder = new OneHolder(convertView);
convertView.setTag(oneHolder);
} else {
oneHolder = (OneHolder) convertView.getTag();
}
oneHolder.bindData(position, entity);
break;
case TYPE_TWO:
...
break;
}
return convertView;
}
}
每個(gè) item 的數(shù)據(jù)處理是在單獨(dú)一個(gè) ViewHolder 上處理撩独,ViewHolder 中的處理如下:
- 做 findViewById 和數(shù)據(jù)渲染的處理
public class OneHolder {
TextView tv_01;
TextView tv_02;
// 獲取到每個(gè)Item View的引用
/**
* 可傳入?yún)?shù):convertView / datas
**/
//public OneHolder(View convertView) {
public OneHolder(View convertView, List<T> datas) {
this.mDatas = datas;
if (convertView != null) {
// 這里做 findViewById操作
tv_01 = (TextView)convertView.findViewById(R.id.tv_01);
}
}
/**
* 要顯示的數(shù)據(jù)對(duì)象
* 可傳入?yún)?shù):position
**/
public void bindData(int position, NewEntity entity) {
String title = entity.getTitle();
tv_01.setText(String.valueOf(title));
}
}
有時(shí)候 ViewHolder 中想要操作 Adapter 中的 datas 這時(shí)候,可以在構(gòu)造函數(shù)上加個(gè)參數(shù)
// 獲取到每個(gè)Item View的引用
public OneHolder(View convertView, List<Object> list) {
if (convertView != null) {
// 這里做 findViewById操作
tv_01 = (TextView)convertView.findViewById(R.id.tv_01);
}
}
BaseHolder 簡(jiǎn)單抽取
public abstract class BaseHolder<T> {
public List<T> mDatas;
public void bindData(List<T> datas) {
this.mDatas = datas;
}
public BaseHolder(int position);
}