上篇Android ListView中複雜數據流的高效渲染文章中介紹如何高效利用ListView的緩存進行渲染。以後有挺多同窗有些疑惑,但願能夠有一個demo,因而利用業餘時間把demo櫓出來了,若是有什麼問題你們能夠評論或者在ComplexDataStream issue中提issue。這裏貼一下demo的地址:ComplexDataStream。另我的以爲這個思路實際增長了代碼複雜度,在邏輯上並不高效,因而在題目中加了引號,可是實測一個複雜列表中能夠節約10-20m的內存,這一點是頗有誘惑力的。下面結合代碼介紹一下。javascript
Adapter
Adapter中放置了adapter和各類類型的holder,這裏把多種數據類型拆分紅了card、divider、header、image、link、text、title,併爲每種類型設置了相應的佈局。java
Util
Util中設置如何transform數據到相應的展現模版,以及解決按壓效果的問題。git
咱們的目的是將複雜的數據類型進行拆分,從而達到細顆粒的view複用,下降內存佔用。github
public enum ItemType {
TITLE,
CARD,
HEADER,
IMAGE,
TEXT,
LINK,
DIVIDER
}複製代碼
private static Map<Class, List<ItemType>> map = new HashMap<>();複製代碼
public static List<ItemWrap> getTransformedItem(List<BaseItem> baseItems) {
List<ItemWrap> itemWraps = new ArrayList<>();
for (BaseItem baseItem : baseItems) {
for (ItemType itemType : map.get(baseItem.getClass())) {
ItemWrap temp = new ItemWrap(baseItem, itemType);
itemWraps.add(temp);
baseItem.itemWraps.add(temp);
}
ItemWrap divider = new ItemWrap(baseItem, ItemType.DIVIDER);
itemWraps.add(divider);
baseItem.itemWraps.add(divider);
}
return itemWraps;
}複製代碼
getTransformedItem方法將原始數據進行拆分,注意每種原始數據類型中都要加入divider模板,用於展現ListView的分割線。public static View createItemView(ItemType itemType) {
View view = null;
BaseHolder baseHolder = null;
switch (itemType) {
case TITLE:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.title_item, null);
baseHolder = new TitleHolder();
break;
case CARD:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.card_item, null);
baseHolder = new CardHolder();
break;
case TEXT:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.text_item, null);
baseHolder = new TextHolder();
break;
case IMAGE:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.image_item, null);
baseHolder = new ImageHolder();
break;
case LINK:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.link_item, null);
baseHolder = new LinkHolder();
break;
case HEADER:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.header_item, null);
baseHolder = new HeaderHolder();
break;
case DIVIDER:
view = LayoutInflater.from(_Application.applicationContext).inflate(R.layout.divider_item, null);
baseHolder = new DividerHolder();
break;
}
baseHolder.setup(view);
view.setTag(baseHolder);
return view;
}複製代碼
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
if (mListener != null) {
mListener.onStatePress(false);
}
} else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (mListener != null) {
mListener.onStatePress(true);
}
} else if (ev.getAction() == MotionEvent.ACTION_CANCEL) {
if (mListener != null) {
mListener.onStatePress(false);
}
}
super.dispatchTouchEvent(ev);
return true;
}複製代碼
能夠完成view按壓的回調。@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemWrap itemWrap = (ItemWrap) getItem(position);
if(convertView == null){
convertView = ItemWrapHelper.getItemView(itemWrap.getItemType());
}else {
((ItemWrap)(convertView.getTag(R.string.tag_key))).unBindView();
}
convertView.setTag(R.string.tag_key, itemWrap);
BaseHolder baseHolder = (BaseHolder) convertView.getTag();
baseHolder.render(itemWrap.getBaseItem());
itemWrap.bindView(convertView);
return convertView;
}複製代碼
基本demo就完成了,按壓效果如圖:歡迎關注公衆號wutongke,天天推送移動開發前沿技術文章:緩存