【Android】ListView使用BaseAdapter異常顯示小結

  • ListView和Adapter的基礎知識html

【問】假如Listview的item數量有10億條的話豈不是要繪製10億個View?java

【答】確定不可能,手機內容會沒那麼大...Android針對這種狀況專門設計了Recycler的構件緩存

【參考】http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.htmlide

【概要】佈局

假如一個頁面只能顯示10條list內容,且每一個條目的樣式是同樣的spa

那麼50條內容的顯示,其實只是1~10條會繪製頁面 [ convertView仍然是空值 ]設計

            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.item1, null);
                holder = new ViewHolder();
                holder.textView = (TextView)convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            }
 

當編號爲1的條目向上滑動移出屏幕以後[View-1]code

編號爲11的條目自下進入屏幕,將會直接套用[View-1]orm

else {
                holder = (ViewHolder)convertView.getTag();
            }


  • 看看代碼
    htm

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        // 提升刷新的效率,避免卡頓
        // 當子條目容器爲空的時候,填充佈局式樣
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.adapter_circle_msg_item, null);
            holder = new ViewHolder(convertView);
            // setTag的妙用
            // 綁定convertView與ViewHolder貼上Tag
            convertView.setTag(holder);
        } else {
            // setTag的妙用
            // 當convertView非空時候,直接根據Tag拿到綁定的ViewHolder【存放在緩存中的】
            holder = (ViewHolder) convertView.getTag();
        }
        CircleMsgItemInfo info = mInfos.get(position);
        holder.fillViewWithData(info);
        return convertView;
    }

代碼解析

  • setTag方法是幹什麼的?
    setTag給View對象的一個標籤,標籤能夠是任何內容,咱們這裏把他設置成了一個對象

ViewHolder holder;
...
convertView.setTag(holder);

由於咱們先抽象出來成爲一個內部類ViewHolder,用了setTag,這個標籤就是ViewHolder實例化後對象的一個屬性。
咱們以後對於ViewHolder實例化的對象holder的操做,都會由於java的引用機制而一直存活並改變convertView的內容,而不是每次都是去new一個,而達到重用的效果。


  • 不使用Tag標籤會怎麼樣呢?

第一種狀況:當UI容器沒用使用LayoutInflater進行View填充的時候,不必使用。

第二種狀況:當UI容器使用LayoutInflater進行View填充的時候,不使用Tag機制會形成滑動卡頓


  • 使用Tag的必要性?

當ListView中每個item的佈局都不同的時候,就不須要使用Tag

Tag標誌是爲了,提交重用的目的擬出的,沒有一樣的佈局就沒有意義了


  • Listview滑動UI顯示異常的問題

【1】顯示順序異常的問題1-2-3-4-5-6-7-8,滑動以後可能變成2-3-4-5-6-7-8-1?

該問題在我工程中遇到的問題具備特殊性:一共只有8個item條目,且每一個佈局都不同

問題處理:取代哦setTag的邏輯

【2】滑動後頁面顯示異常,A條目的內容可能跟B條目的內容混雜在一塊兒

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            ...
            convertView.setTag(holder);
        } else {

            holder = (ViewHolder) convertView.getTag();
        }
        CircleMsgItemInfo info = mInfos.get(position);
        holder.fillViewWithData(info);
        return convertView;
    }

public void fillViewWithData(CircleMsgItemInfo info) {
            showHeaderBackground(info.getReplyHeadImg());
            name.setText(info.getReplyName());
            if (info.getReplyType().equals("like")) {
                content.setText(R.string.friend_circle_like);
                content.setTextColor(mContext.getResources().getColor(
                        R.color.blue_95));
                TextPaint tp = content.getPaint();
                tp.setFakeBoldText(true);
            } else {
                content.setText(EmojiUtil.formatEmoji(mContext, info.getReplyContent()));
                content.setTextColor(mContext.getResources().getColor(
                        R.color.black));
                TextPaint tp = content.getPaint();
                tp.setFakeBoldText(false);
            }
            time.setText(FriendlyDateFormat.formatTime(info.getReplyTime()));
        }

這是因爲Android回收機制致使的,由於設置重用,避免單條View的從新繪製。

fillViewWithData在填充數據的時候,若是沒有將item每個內容都重寫一遍的話,遺漏的部分將使用以前item中的內容

事例:

item Old  data : A B C D E

item New date : a    c d e {注意沒有 b }

那麼顯示的效果 : a B c d e

相關文章
相關標籤/搜索