android:Listview和recycleview的內存優化原理

吐槽:一直想寫一篇完整的,能系統地介紹某個知識點的文章,但由于技術不夠加上懶,只能仰望其他大神寫出的非常優秀的文章,從中學習一二。今天看了hongyang大神寫的關于recycleview的博客,獲益良多啊!不過鴻神可能要全面解析這個控件,沒那么多篇幅來寫一些原理問題,所以我google了一番結合listview來介紹他們的優化原理(作為初學者,我僅憑自己理解去寫這篇文章,如有錯誤,你來打我啊(開玩笑...),還是非常希望各位能及時幫我更正)

首先我們來看下,沒有優化過的listview中getView方法(因為是介紹原理問題,所有的代碼就不貼上了,百度一大堆)

@Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //listview_item里只有一個textview
            View view = View.inflate(MainActivity.this, R.layout.listview_item,
                    null);
            //使用每一次都findviewById的方法來獲得listview_item內部的組件
            TextView tv_item = (TextView) view.findViewById(R.id.tv_item);
            tv_item.setText(list.get(position));
            return view;
        }

當我們的item有十幾個的時候,手機屏幕不足以完全顯示(說iphone18的走開!!),所以我們要向上滑動以顯示下面其他的item,但這時前面的item就會淡出屏幕,再向下滑動,又顯示前面的item了,但你會發現,無論顯示第一個item還是顯示最后一個item,只要出現在屏幕上一次,就會調用一次getView來創建這個item。這無疑是很浪費內存的,所以就有下面的優化方案。

public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            ViewHolder holder;
            // 判斷convertView的狀態,來達到復用效果
            if (null == convertView) {
                // 如果convertView為空,則表示第一次顯示該條目,需要創建一個view
                view = View.inflate(MainActivity.this, R.layout.listview_item,
                        null);
                //新建一個viewholder對象
                holder = new ViewHolder();
                //將findviewbyID的結果賦值給holder對應的成員變量
                holder.tvHolder = (TextView) view.findViewById(R.id.tv_item);
                // 將holder與view進行綁定
                view.setTag(holder);
            } else {
                // 否則表示可以復用convertView
                view = convertView;
                holder = (ViewHolder) view.getTag();
            }
            // 直接操作holder中的成員變量即可,不需要每次都findViewById
            holder.tvHolder.setText(list.get(position));
            return view;
        }

convertView這個參數設計非常巧妙,是用來儲存那些被你萬惡的手指滑動導致淡出的item,當它為空,說明之前沒有被創建過,所以就創建這個item,它不為空時,嘿嘿,說明是被淡出的item,之前有被創建,那就直接拿出來用就行啦。關于ViewHolder很多資料也有介紹,這里也不再贅述了。來看下圖更有利于理解:


Paste_Image.png

上面是ListView的。接下來我們來看下RecycleView:

package com.example.q_recycler;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

/**
 * Created by 強強 on 2017/2/6.
 */

public class MyRecycleviewAdapter extends RecyclerView.Adapter<MyRecycleviewAdapter.ViewHolder>{

    List<String> list;

    public MyRecycleviewAdapter(List<String> list){
        this.list=list;
    }

    @Override
    public MyRecycleviewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.id_num,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.tv.setText(list.get(position));
    }

    @Override
    public int getItemCount() {
        if(list!=null) return list.size();
        else
            return 0;
    }

     class ViewHolder extends RecyclerView.ViewHolder {
       public TextView tv;
        public ViewHolder(View itemView) {
            super(itemView);
            tv= (TextView) itemView.findViewById(R.id.id_num);
        }
    }
}

RecycleView作為ListView的升級版,自然有它的優勢,拋棄那n多的功能(被鴻神稱為藝術般的控件),它的內存優化也是獨到的哦。

我的理解是:RecycleView提供了一個緩存機制,當一個item沒有被創建時,就會調用onCreateViewHolder的方法創建這個item,同時也放入到緩存中,以ViewHolder的形式返回,當要顯示item時,就會在緩存中尋找有沒有創建過這個item,如果創建了的話就直接調用onBindViewHolder方法進行渲染顯示。這里也避免重復創建item了,可見,它們的優化原理是相差無幾的,結合起來更能讓人理解。

結束語:這又是一片簡文(好符合簡書哦),文中只介紹了我對于這兩個控件的一點點見解(個人理解),不敢肯定百分百是對的。還有,文中還有很多東西沒有介紹到,因為我認為很多大神都對它們有非常詳細的博客(懶),隨便一搜就可以看到了,我再寫的話,,,會很累的!!!!哈哈,下面貼兩個詳解博客吧
http://blog.csdn.net/skykingf/article/details/50827141

http://blog.csdn.net/lmj623565791/article/details/45059587

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容