1. 程式人生 > >Android必學之資料介面卡BaseAdapter

Android必學之資料介面卡BaseAdapter

什麼是資料介面卡?

下圖展示了資料來源、介面卡、ListView等資料展示控制元件之間的關係。我們知道,資料來源是各種各樣的,而ListView所展示資料的格式則是有一定的要求的。資料介面卡正是建立了資料來源與ListView之間的適配關係,將資料來源轉換為ListView能夠顯示的資料格式,從而將資料的來源與資料的顯示進行解耦,降低程式的耦合性。這也體現了Android的介面卡模式的使用。對於ListView、GridView等資料展示控制元件有多種資料介面卡,本文講解最通用的資料介面卡——BaseAdapter。

.ListView的顯示與快取機制

我們知道,ListView、GridView等控制元件可以展示大量的資料資訊。假如下圖中的ListView可以展示100條資訊,但是螢幕的尺寸是有限的,一螢幕只能顯示下圖中的7條。當向上滑動ListView的時候,item1被滑出了螢幕區域,那麼系統就會將item1回收到Recycler中,即View緩衝池中,而將要顯示的item8則會從快取池中取出佈局檔案,並重新設定好item8需要顯示的資料,並放入需要顯示的位置。這就是ListView的緩衝機制,總結起來就是一句話:需要時才顯示,顯示完就被會收到快取。ListView,GridView等資料顯示控制元件通過這種快取機制可以極大的節省系統資源。

.BaseAdapter

使用BaseAdapter比較簡單,主要是通過繼承此類來實現BaseAdapter的四個方法:

public int getCount(): 介面卡中資料集的資料個數;

public Object getItem(int position): 獲取資料集中與索引對應的資料項;

public long getItemId(int position): 獲取指定行對應的ID;

public View getView(int position,View convertView,ViewGroup parent): 獲取沒一行Item的顯示內容。

下面通過一個簡單示例演示如何使用BaseAdapter。

1.建立佈局檔案

activity_main.xml

複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.cbt.learnbaseadapter.MainActivity">

    <ListView
        android:id="@+id/lv_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</RelativeLayout>
複製程式碼

item.xml (ListView中每條資訊的顯示佈局)

複製程式碼
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iv_image"
        android:src="@mipmap/ic_launcher"
        android:layout_width="60dp"
        android:layout_height="60dp"/>
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_toEndOf="@id/iv_image"
        android:text="Title"
        android:gravity="center"
        android:textSize="25sp"/>

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toEndOf="@id/iv_image"
        android:layout_below="@id/tv_title"
        android:text="Content"
        android:textSize="20sp"/>
</RelativeLayout>
複製程式碼

2.建立資料來源

ItemBean.java

複製程式碼
package com.cbt.learnbaseadapter;

/**
 * Created by caobotao on 15/12/20.
 */
public class ItemBean {
    public int itemImageResId;//影象資源ID
    public String itemTitle;//標題
    public String itemContent;//內容

    public ItemBean(int itemImageResId, String itemTitle, String itemContent) {
        this.itemImageResId = itemImageResId;
        this.itemTitle = itemTitle;
        this.itemContent = itemContent;
    }
}
複製程式碼

通過此Bean類,我們就將要顯示的資料與ListView的佈局內容一一對應了,每個Bean物件對應ListView的一條資料。這種方法在ListView中使用的非常廣泛。

MainActivity.java

複製程式碼
package com.cbt.learnbaseadapter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    ListView mListView ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        List<ItemBean> itemBeanList = new ArrayList<>();
        for (int i = 0;i < 20; i ++){
            itemBeanList.add(new ItemBean(R.mipmap.ic_launcher, "標題" + i, "內容" + i));
        }
        mListView = (ListView) findViewById(R.id.lv_main);
        //設定ListView的資料介面卡
        mListView.setAdapter(new MyAdapter(this,itemBeanList));
    }
}
複製程式碼

3.建立BaseAdapter

通過上面的講解,我們知道繼承BaseAdapter需要重新四個方法:getCount、getItem、getItemId、getView。其中前三個都比較簡單,而getView稍微比較複雜。通常重寫getView有三種方式,這三種方法效能方面有很大的不同。接下來我們使用此三種方式分別實現MyAdapter。

第一種:逗比式

複製程式碼
package com.cbt.learnbaseadapter;
import android.content.Context;
import android.view.*;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
/**
 * Created by caobotao on 15/12/20.
 */
public class MyAdapter extends BaseAdapter{
    private List<ItemBean> mList;//資料來源
    private LayoutInflater mInflater;//佈局裝載器物件

    // 通過構造方法將資料來源與資料介面卡關聯起來
    // context:要使用當前的Adapter的介面物件
    public MyAdapter(Context context, List<ItemBean> list) {
        mList = list;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    //ListView需要顯示的資料數量
    public int getCount() {
        return mList.size();
    }

    @Override
    //指定的索引對應的資料項
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    //指定的索引對應的資料項ID
    public long getItemId(int position) {
        return position;
    }

    @Override
    //返回每一項的顯示內容
    public View getView(int position, View convertView, ViewGroup parent) {
        //將佈局檔案轉化為View物件
        View view = mInflater.inflate(R.layout.item,null);

        /**
         * 找到item佈局檔案中對應的控制元件 
         */
        ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);
        TextView titleTextView = (TextView) view.findViewById(R.id.tv_title);
        TextView contentTextView = (TextView) view.findViewById(R.id.tv_content);

        //獲取相應索引的ItemBean物件
        ItemBean bean = mList.get(position);

        /**
         * 設定控制元件的對應屬性值 
         */
        imageView.setImageResource(bean.itemImageResId);
        titleTextView.setText(bean.itemTitle);
        contentTextView.setText(bean.itemContent);

        return view;
    }
}
複製程式碼

為什麼稱這種getView的方式是逗比式呢?

通過上面講解,我們知道ListView、GridView等資料展示控制元件有快取機制,而這種方式每次呼叫getView時都是通過inflate建立一個新的View物件,然後在此view中通過findViewById找到對應的控制元件,完全沒有利用到ListView的快取機制。這種方式沒有經過優化處理,對資源造成了極大的浪費,效率是很低的。

第二種:普通式

複製程式碼
public View getView(int position, View convertView, ViewGroup parent) {//如果view未被例項化過,快取池中沒有對應的快取
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item,null);
        }
        /**
         * 找到item佈局檔案中對應的控制元件
         */
        ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);
        TextView titleTextView = (TextView) convertView.findViewById(R.id.tv_title);
        TextView contentTextView = (TextView) convertView.findViewById(R.id.tv_content);

        //獲取相應索引的ItemBean物件
        ItemBean bean = mList.get(position);
        /**
         * 設定控制元件的對應屬性值
         */
        imageView.setImageResource(bean.itemImageResId);
        titleTextView.setText(bean.itemTitle);
        contentTextView.setText(bean.itemContent);
        return convertView;
    }
複製程式碼

此方式充分使用了ListView的快取機制,如果view沒有快取才建立新的view,效率相比於逗比式提升了很多。但是,當ListView很複雜時,每次呼叫findViewById都會去遍歷檢視樹,所以findViewById是很消耗時間的,我們應該儘量避免使用findViewById來達到進一步優化的目的。

第三種:文藝式

複製程式碼
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder;
    //如果view未被例項化過,快取池中沒有對應的快取
    if (convertView == null) {
        viewHolder = new ViewHolder();
        // 由於我們只需要將XML轉化為View,並不涉及到具體的佈局,所以第二個引數通常設定為null
        convertView = mInflater.inflate(R.layout.item, null);

        //對viewHolder的屬性進行賦值
        viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
        viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title);
        viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content);

        //通過setTag將convertView與viewHolder關聯
        convertView.setTag(viewHolder);
    }else{//如果快取池中有對應的view快取,則直接通過getTag取出viewHolder
        viewHolder = (ViewHolder) convertView.getTag();
    }
    // 取出bean物件
    ItemBean bean = mList.get(position);

    // 設定控制元件的資料
    viewHolder.imageView.setImageResource(bean.itemImageResId);
    viewHolder.title.setText(bean.itemTitle);
    viewHolder.content.setText(bean.itemContent);

    return convertView;
}
// ViewHolder用於快取控制元件,三個屬性分別對應item佈局檔案的三個控制元件
class ViewHolder{
    public ImageView imageView;
    public TextView title;
    public TextView content;
}
複製程式碼

此方式不僅利用了ListView的快取機制,而且使用ViewHolder類來實現顯示資料檢視的快取,避免多次呼叫findViewById來尋找控制元件,以達到優化程式的目的。所以,大家在平時的開發中應當儘量使用這種方式進行getView的實現。

總結一下用ViewHolder優化BaseAdapter的整體步驟:

>1 建立bean物件,用於封裝資料;

>2 在構造方法中初始化的資料List;

>3 建立ViewHolder類,建立佈局對映關係;

>4 判斷convertView,為空則建立,並設定tag,不為空則通過tag取出ViewHolder;

>5 給ViewHolder的控制元件設定資料。

相關推薦

Android資料介面卡BaseAdapter

什麼是資料介面卡? 下圖展示了資料來源、介面卡、ListView等資料展示控制元件之間的關係。我們知道,資料來源是各種各樣的,而ListView所展示資料的格式則是有一定的要求的。資料介面卡正是建立了資料來源與ListView之間的適配關係,將資料來源轉換為ListView能夠顯示的資料格式,從而將資料的來

未雨綢繆:Java高階架構進階 ⑥ 大知識要點附視訊學習資料

程式設計師,一個令人嚮往的職業,看起來有著高薪酬、高技術,還是一群高智商、頭腦靈活的人。事實上,程式設計師的工作,讓人非常抓狂,程式設計師的生活,異常線性單調。而且技術更新快,相互之間競爭壓力非常大~~ 相信你可能經歷過這些: 已經工作3年了,每個專案都會保質保量的完成,

Python入門資料型別和變數的用法

什麼是資料型別?計算機顧名思義就是可以做數學計算的機器,因此,計算機程式理所當然地可以處理各種數值。但是,計算機能處理的遠不止數值,還可以處理文字、圖形、音訊、視訊、網頁等各種各樣的資料,不同的資料,需要定義不同的資料型別。在Python中,能夠直接處理的資料型別有以下幾種: 整數 Pytho

android面試題資料結構篇

1.常見的資料結構介紹   https://www.jianshu.com/p/230e6fde9c75(轉) 2.常見的5種併發集合 1、常用的五種併發包 ConcurrentHashMap CopyOnWriteArrayList CopyOnWr

Python 爬蟲工程師——App資料抓取實戰

第1章 課程介紹 介紹課程目標、通過課程能學習到的內容、學會這些技能能做什麼,對公司業務有哪些幫助,對個人有哪些幫助。介紹目前app資料抓取有哪些困難,面臨的挑戰,本實戰課程會利用哪些工具來解決這些問題,以及本實戰課程的特點 ... 1-1 python爬蟲工程師必備技

某課《Python 爬蟲工程師 App資料抓取實戰》

第1章 課程介紹 介紹課程目標、通過課程能學習到的內容、學會這些技能能做什麼,對公司業務有哪些幫助,對個人有哪些幫助。介紹目前app資料抓取有哪些困難,面臨的挑戰,本實戰課程會利用哪些工具來解決這些問題,以及本實戰課程的特點 ... 1-1 python爬蟲工程師必備技

Python 爬蟲工程師 App資料抓取實戰

第5章 移動端自動化控制工具詳講 本章首先介紹了android開發環境的安裝,為講解uiautomatorviewer工具做準備,android開發環境安裝成功後介紹了uiautomatorviewer工具對app應用介面進行分析,節點定位、xpath編寫 介紹了appium-desktop工具的錄製

Python 爬蟲工程師 App資料抓取實戰目前最完整

第1章 課程介紹 介紹課程目標、通過課程能學習到的內容、學會這些技能能做什麼,對公司業務有哪些幫助,對個人有哪些幫助。介紹目前app資料抓取有哪些困難,面臨的挑戰,本實戰課程會利用哪些工具來解決這些問題,以及本實戰課程的特點 ... 1-1 python爬蟲工程師必備技

【EasyUi】頁面設計Layout

        接觸EasyUi也快一年了,很多時候都把重心放在實現功能方面,要顯示大量資料了就用DataGrid,要實現分頁效果了就想著Tabs,如此等等,再接下來就是考慮CSS、js如何讓這個功能實現的更好。我很少去看其它“無關”功能的東西,每次總以沒時間為由推遲對這些

資料介面卡---BaseAdapter

文章詳細介紹了資料介面卡BaseAdapter三種使用方法。 程式碼: Xml檔案:activity_main <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="ht

android 藍芽資料傳輸

因為專案需要,需要將本地資料庫的資料,通過藍芽傳輸到另一臺裝置上。然後百度了蠻久,看了蠻多的,覺得有必要自己整理一下,藍芽的傳輸功能。 首先,我們都知道的,藍芽連線數需要先配對的,兩臺手機配對後才可進行藍芽處理。對於藍芽配對的方法網上一大堆,我也就不具體說了,大概記錄一

Python編譯器用哪個好?你用錯了吧!

當我們編寫Python程式碼時,我們得到的是一個包含Python程式碼的以.py為副檔名的文字檔案。要執行程式碼,就需要Python直譯器去執行.py檔案。 由於整個Python語言從規範到直譯器都是開源的,所以理論上,只要水平夠高,任何人都可以編寫Pytho

四、Android安全機制資料加密

    MD5,全名Message Digest Algorithm 5 ,中文名為訊息摘要演算法第五版,一種不可逆的hash演算法,常用於只需加密無需解密的資料上,比如使用者密碼,也常用來保證資料的完整性,因為資料被篡改後,其加密後的MD5也會隨之改變(不考慮碰撞的情況下),對比篡改前的MD5可確定資料是

資料入門技術Hadoop

Hadoop是一個能夠對大量資料進行分散式處理的軟體框架。使用者可以輕鬆地在Hadoop上開發和執行處理海量資料的應用程式,在大資料領域應用比較多。本文就和大家一起認識一下Hadoop技術:   1 Hadoop歷史   雛形開始於2002年的Apache的N

Android進階:自定義註解動態代理

自定義註解是Android進階的必學知識,從現在起我講為大家帶來四篇文章,讓大家徹底學會自定義註解 靜態代理大家都明白,就是相當於包裝了一次,在包裝這一次的時候可以加一些業務邏輯。同樣靜態代理的特點是一個介面對應一個代理類,當然委託類可以多個。 靜態

架構路—java開發知識點詳細梳理

編程語言 Java 設計模式 Redis MySQL 大家好,今天為大家帶來了java開發必學的知識點的梳理,希望對小夥伴們在技術成長的道路上有所幫助。 數據庫 mysql 1、sql基本語法(數據類型、增刪改查、join、函數等)。 2、索引(分類,失效條件,explain的使用,優化條

零基礎大資料學習技術有哪幾種,你知道嗎?

現在大資料非常火爆,不管是阿里巴巴、百度、騰訊這樣的大企業,還是中小型的企業都非常重視,大資料也是第一個納入國家戰略的技術。今天為大家講一下零基礎大資料學習必學技術有哪幾種。 大資料給大多數人的感覺是,專業性強,屬於“高大上”的技術。一部分人對大資料比較感興趣,會上網搜尋一些概念性的簡單瞭解,而

資料學習小白如何資料?(詳細篇)

大資料這個話題熱度一直高居不下,不僅是國家政策的扶持,也是科技順應時代的發展。想要學習大資料,我們該怎麼做呢?大資料學習路線是什麼?先帶大家瞭解一下大資料的特徵以及發展方向。 大資料的三個發展方向,平臺搭建/優化/運維/監控、大資料開發/設計/架構、資料分析/挖掘。 先說一下大資料的4V特徵: 資料

零基礎大資料學習技術有哪幾種?

現在大資料非常火爆,不管是阿里巴巴、百度、騰訊這樣的大企業,還是中小型的企業都非常重視,大資料也是第一個納入國家戰略的技術。今天為大家講一下零基礎大資料學習必學技術有哪幾種。 大資料給大多數人的感覺是,專業性強,屬於“高大上”的技術。一部分人對大資料比較感興趣,會上網搜尋一些概念性的簡單瞭解,而有一些人則看

一起來資料|Mybatis如魚得水的動態SQL,百樣玲瓏?

  昨天,我們就學習了mybatis的 一下相關的知識,文章開頭我們級提到它可以解決SQL的硬編碼問題,但是根據昨天的文章,我們並沒有看出mybatis的優勢。今天我們來使用mybatis中的動態sql來解決我們仍有的困惑。 動態 SQL 在mybatis框架中,動態