1. 程式人生 > >ListView介面卡及快取機制

ListView介面卡及快取機制

ListView和介面卡的基礎:
它是如何工作的:

  • ListView 向介面卡說“給我的每個條目一個佈局”
  • 一個新的佈局創建出來並顯示出來

下一個問題:當我們有10億個條目的時候怎麼辦,難道新建立一個新的佈局並顯示出來嗎?答案肯定是“不”。Android會為你把佈局快取起來。
這一部分在Android中稱呼為"Recycle - 回收利用"。以下為它的具體實現過程圖。
 

  • 當你有一億個條目的時候, 只有可看見的View儲存在記憶體中+Recycle過的View
  • 當ListView第一次向介面卡請求一個VIew的時候,convertView為null,因此需要新建一個convertView.
  • 當ListView請求一個條目item1的VIew,並且item1已經超出螢幕之外,並進來一個相同型別的條目從底部進入到螢幕裡面,這時convertVIew 不為null,而是等於item1。 你只需要獲取新的資料裝載到該View裡面並返回回去。而不必要重新建立一個新的VIew

下面為簡單的程式碼實現:

public class MultipleItemsList extends ListActivity {
 
    private MyCustomAdapter mAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 0; i < 50; i++) {
            mAdapter.addItem("item " + i);
        }
        setListAdapter(mAdapter);
    }
 
    private class MyCustomAdapter extends BaseAdapter {
 
        private ArrayList mData = new ArrayList();
        private LayoutInflater mInflater;
 
        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }
 
        @Override
        public int getCount() {
            return mData.size();
        }
 
        @Override
        public String getItem(int position) {
            return mData.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("getView " + position + " " + convertView);
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.item1, null);
                holder = new ViewHolder();
                holder.textView = (TextView)convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }
 
    }
 
    public static class ViewHolder {
        public TextView textView;
    }
}

執行程式並觀察發生了什麼

getView方法呼叫了9次。對於可以看見的VIew中,convertView一直為null。

  1. 02-05 13:47:32.559: INFO/System.out(947): getView 0 null
  2. 02-05 13:47:32.570: INFO/System.out(947): getView 1 null
  3. 02-05 13:47:32.589: INFO/System.out(947): getView 2 null
  4. 02-05 13:47:32.599: INFO/System.out(947): getView 3 null
  5. 02-05 13:47:32.619: INFO/System.out(947): getView 4 null
  6. 02-05 13:47:32.629: INFO/System.out(947): getView 5 null
  7. 02-05 13:47:32.708: INFO/System.out(947): getView 6 null
  8. 02-05 13:47:32.719: INFO/System.out(947): getView 7 null
  9. 02-05 13:47:32.729: INFO/System.out(947): getView 8 null
複製程式碼
拖動以下,並檢視輸出的狀態。

  1. 02-05 14:01:31.069: INFO/System.out(947): getView 11 [email protected]
  2. 02-05 14:01:31.142: INFO/System.out(947): getView 12 [email protected]
  3. 02-05 14:01:31.279: INFO/System.out(947): getView 13 [email protected]
  4. 02-05 14:01:31.350: INFO/System.out(947): getView 14 [email protected]
  5. 02-05 14:01:31.429: INFO/System.out(947): getView 15 [email protected]
  6. 02-05 14:01:31.550: INFO/System.out(947): getView 16 [email protected]
  7. 02-05 14:01:31.669: INFO/System.out(947): getView 17 [email protected]
  8. 02-05 14:01:31.839: INFO/System.out(947): getView 18 [email protected]
  9. 02-05 14:03:30.900: INFO/System.out(947): getView 19 [email protected]
  10. 02-05 14:03:32.069: INFO/System.out(947): getView 20 [email protected]
複製程式碼

就像我們所想到的一樣,convertView不為null.當item11超出螢幕之後,並進來item21的時候2個convertView為同一個View。


不同的列表條目的View
我們舉一個更加複雜點的例子吧,我們加入一個分隔符到ListView中。
你需要做的是:
  • 重寫getViewTypeCount()   ->它返回不同的View的個數
  • getItemViewType(int) -> 根據它的位置返回正確的View型別
  • Create correct convertView (depending on view item type) in getView
下面為程式碼:

public class MultipleItemsList extends ListActivity {
 
    private MyCustomAdapter mAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("item " + i);
            if (i % 4 == 0) {
                mAdapter.addSeparatorItem("separator " + i);
            }
        }
        setListAdapter(mAdapter);
    }
 
    private class MyCustomAdapter extends BaseAdapter {
 
        private static final int TYPE_ITEM = 0;
        private static final int TYPE_SEPARATOR = 1;
        private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
 
        private ArrayList mData = new ArrayList();
        private LayoutInflater mInflater;
 
        private TreeSet mSeparatorsSet = new TreeSet();
 
        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }
 
        public void addSeparatorItem(final String item) {
            mData.add(item);
            // save separator position
            mSeparatorsSet.add(mData.size() - 1);
            notifyDataSetChanged();
        }
 
        @Override
        public int getItemViewType(int position) {
            return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
        }
 
        @Override
        public int getViewTypeCount() {
            return TYPE_MAX_COUNT;
        }
 
        @Override
        public int getCount() {
            return mData.size();
        }
 
        @Override
        public String getItem(int position) {
            return mData.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            int type = getItemViewType(position);
            System.out.println("getView " + position + " " + convertView + " type = " + type);
            if (convertView == null) {
                holder = new ViewHolder();
                switch (type) {
                    case TYPE_ITEM:
                        convertView = mInflater.inflate(R.layout.item1, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.text);
                        break;
                    case TYPE_SEPARATOR:
                        convertView = mInflater.inflate(R.layout.item2, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
                        break;
                }
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }
 
    }
 
    public static class ViewHolder {
        public TextView textView;
    }

我們執行並檢視以下我們寫的程式碼所輸出的東西,我們會發現每隔4個條目它會出現一個分隔符。




檢視輸出Log,沒有什麼特別的對於不同的型別 convertView都為Null

  1. 02-05 15:19:03.080: INFO/System.out(1035): getView 0 null type = 0
  2. 02-05 15:19:03.112: INFO/System.out(1035): getView 1 null type = 0
  3. 02-05 15:19:03.130: INFO/System.out(1035): getView 2 null type = 0
  4. 02-05 15:19:03.141: INFO/System.out(1035): getView 3 null type = 0
  5. 02-05 15:19:03.160: INFO/System.out(1035): getView 4 null type = 1
  6. 02-05 15:19:03.170: INFO/System.out(1035): getView 5 null type = 0
  7. 02-05 15:19:03.180: INFO/System.out(1035): getView 6 null type = 0
  8. 02-05 15:19:03.190: INFO/System.out(1035): getView 7 null type = 0
  9. 02-05 15:19:03.210: INFO/System.out(1035): getView 8 null type = 0
  10. 02-05 15:19:03.210: INFO/System.out(1035): getView 9 null type = 1
複製程式碼

拖動一下,看看Log中有什麼變化
  1. 02-05 15:19:54.160: INFO/System.out(1035): getView 10 null type = 0
  2. 02-05 15:19:57.440: INFO/System.out(1035): getView 11 [email protected] type = 0
  3. 02-05 15:20:01.310: INFO/System.out(1035): getView 12 [email protected] type = 0
  4. 02-05 15:20:01.880: INFO/System.out(1035): getView 13 [email protected] type = 0
  5. 02-05 15:20:02.869: INFO/System.out(1035): getView 14 null type = 1
  6. 02-05 15:20:06.489: INFO/System.out(1035): getView 15 [email protected] type = 0
  7. 02-05 15:20:07.749: INFO/System.out(1035): getView 16 [email protected] type = 0
  8. 02-05 15:20:10.250: INFO/System.out(1035): getView 17 [email protected] type = 0
  9. 02-05 15:20:11.661: INFO/System.out(1035): getView 18 [email protected] type = 0
  10. 02-05 15:20:13.180: INFO/System.out(1035): getView 19 [email protected] type = 1
  11. 02-05 15:20:16.900: INFO/System.out(1035): getView 20 [email protected] type = 0
  12. 02-05 15:20:25.690: INFO/System.out(1035): getView 21 [email protected] type = 0
複製程式碼

分隔符的convertView為Null,直到第一個分隔符看見為止。當它超出螢幕時,View還會快取到Recycler中,以使convertView顯示出來。

相關推薦

ListView介面卡快取機制

ListView和介面卡的基礎:它是如何工作的: ListView 向介面卡說“給我的每個條目一個佈局” 一個新的佈局創建出來並顯示出來下一個問題:當我們有10億個條目的時候怎麼辦,難道新建立一個新的佈局並顯示出來嗎?答案肯定是“不”。Android會為你把佈局快取起來。這

Listview與Recycleview的區別-(用法快取機制

用法上的區別 1、listview的用法 繼承的時BaseAdapter,需要重寫四個方法 不強制使用viewholder 可以直接使用item的點選事件 不用單獨設定分隔線 不可以定向重新整理某一條資料 示例程式碼如下:專案程式碼詳見地址:

梳理hibernate篇-原理快取機制

Hibernate工作原理  本文出自: http://www.cnblogs.com/bile/p/4030575.html  現在我們知道了一個概念Hibernate Session,只有處於Session管理下的POJO才具有持久化操作能力。當應用程式對於處於Sessi

java物件中的三種狀態和髒檢查重新整理快取機制

瞬時狀態   瞬時狀態又稱臨時狀態.如果java物件與資料庫中的資料沒有任何的關聯,即此java物件在資料庫中沒有相關聯的記錄,此時java物件的狀態為瞬時狀態,session對於 瞬時狀態的ava物件是一無所知的,當物件不再被其他物件引用時,它的所有資料也就丟失了,物件將會被java虛擬機器按照垃圾回收

徹底弄懂HTTP快取機制原理

01、前言 Http 快取機制作為 web 效能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的一個基礎環節,同時對於有志成為前端架構師的同學來說是必備的知識技能。僅僅只是知道瀏覽器會對請求的靜態檔案進行快取是不夠的,為什麼被快取,快取是怎樣生效的、

linux下的快取機制清理buffer/cache/swap的方法梳理

free命令用於檢測實體記憶體和交換記憶體已使用量和可用量(預設單位為KB) [[email protected] ~]# free -m //使用-m引數表示以兆位元組為單位顯示記憶體 total used free

Android ListView 與 RecyclerView 對比淺析--快取機制[轉]

轉自https://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653578065&idx=2&sn=25e64a8bb7b5934cf0ce2e49549a80d6&chksm=84b3b156b3c43840061

Mybatis快取機制mybatis的各個組成部分

  Mybatis    一級快取: 基於PerpetualCache 的 HashMap本地快取,其儲存作用域為 Session,當 Session flush 或 close 之後,該Session中的所有 Cache 就將清空。    2. 二級快取與一級快取其機制相同,預設也是採用 Perpetual

ListView 快取機制原始碼淺析

      ListView的快取機制是通過RecycleBin實現對View的快取實現的。快取機制大大的提高了View的複用率,這也是為什麼ListView可以載入大量的Item也不會OOM的原因。當然了,為了進一步提高效能我們都會自定義一個ViewHolder來避免不必

ListView快取機制簡述

listview的快取機制學習自郭霖大神的部落格:https://blog.csdn.net/guolin_blog/article/details/45586553首先要知道listview是個什麼東西,listview和gridview都繼承自AbsListview,而A

ListView和RecyclerView的快取機制的對比

簡單瞭解下快取的基本原理 1)在初始化onLayout過程中,都有一個 mAttachedxxx的集合,臨時存在即將顯示的第一屏的view,在最後一次onLayout結束之後,會從將該mAttachedxxx裡面的view渲染到第一屏頁面上。 2)當向上滑動過程中

【騰訊Bugly乾貨分享】Android ListView與RecyclerView對比淺析--快取機制

作者:黃寧源 一,背景 RecyclerView是谷歌官方出的一個用於大量資料展示的新控制元件,可以用來代替傳統的ListView,更加強大和靈活。 最近,自己負責的業務,也遇到這樣的一個問題,關於是否要將ListView替換為Recycl

探究ListView快取機制

概述 ListView 是繼承AbListView,AbListView是所有列表類控制元件的基類。 ListView的資料載入 在ListView資料載入中最關鍵的一個函式就是makeAndAddView(),這個函式的作用就獲得一個ChildView並把該ChildVie

android之listView快取機制

package com.example.day_05_06; import java.util.ArrayList; import java.util.List; import com.litsoft.General.General; import android.support.v7.app.ActionB

解決ListView 快取機制帶來的顯示不正常問題

ListView載入資料原理:系統繪製ListView時,首先會用getCount()函式得到要繪製的這個列表的長度,然後開始逐行繪製。然後呼叫getView()函式,在這個函式裡面首先獲得一個Vie

各種瀏覽器的快取機制相關問題的解決辦法

一、   <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /><met

【HTTP】徹底弄懂HTTP快取機制原理

前言 Http 快取機制作為 web 效能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的一個基礎環節,同時對於有志成為前端架構師的同學來說是必備的知識技能。 但是對於很多前端同學來說,僅僅只是知道瀏覽器會對請求的靜態檔案進行快取,但是為什麼被快取

SSH:Hibernate框架(Hibernate快取機制三種狀態)

一、why(為什麼要用Hibernate快取?) Hibernate是一個持久層框架,經常訪問物理資料庫。 為了降低應用程式對物理資料來源訪問的頻次,從而提高應用程式的執行效能。 快取內的資料是對物理資料來源中的資料的複製,應用程式在執行時從快取讀寫資料,在特定的時刻或事件會同步快取和物理資料來源的資料。

HTTp快取機制原理

偽*前言一直想總結整理一下關於前端快取相關的內容,希望形成一個系列文章,本篇是第一篇,主要講述HTTP快取機制。系列文章:1.【前端快取--HTTP快取機制】簡單介紹瀏覽器和伺服器是基於什麼規則來實現快取的2.【前端快取--使用者行為對快取的影響】瀏覽器前進,後退,重新整理

Struts2漏洞利用原理OGNL機制

基本 conf 數據集 fig 然而 example 所有 def 字符串類型 Struts2漏洞利用原理及OGNL機制研究 概述 在MVC開發框架中,數據會在MVC各個模塊中進行流轉。而這種流轉,也就會面臨一些困境,就是由於數據在不同MVC層次中表現出不同的形式和狀態