AdapterView
- AdapterView 是一個(gè)抽象類魏颓,其派生的子類在用法上十分相似威蕉;
- AdapterView 繼承了 ViewGroup鼠证;
AdapterView 及其子類的繼承關(guān)系如下:
- AdapterView 常用的實(shí)現(xiàn)類:
- Spinner: 列表選擇框欺矫,當(dāng)需要用戶選擇的時(shí)候沈跨,可以提供一個(gè)列表將所有可選項(xiàng)列出來偷厦,供用戶選擇商叹。
- ListView: 以垂直列表的形式顯示所有列表項(xiàng)。
- GridView: 用于在界面上按行和列分布的方式來顯示多個(gè)組件只泼。
Adapter 接口及其實(shí)現(xiàn)類
- Adapter 是一個(gè)接口剖笙,其派生了 ListAdapter 和 SpinnerAdapter 兩個(gè)子接口。其中请唱,ListAdapter 為 AbsListView 提供列表項(xiàng)弥咪,而 SpinnerAdapter 為AbsSpinner 提供列表項(xiàng)过蹂;
Adapter 及其實(shí)現(xiàn)類的繼承關(guān)系如下:
- Adapter 常用的實(shí)現(xiàn)類:
- ArrayAdapter: 通常用于將數(shù)組或 List 集合的多個(gè)值包裝成多個(gè)列表項(xiàng)。
- SimpleAdapter: 用于將 List 集合的多個(gè)對(duì)象包裝成多個(gè)列表項(xiàng)聚至。
- SimpleCursorAdapter: 與 SimpleAdapter 類似酷勺,與數(shù)據(jù)庫打交道。
- Base Adapter: 抽象類扳躬,通常用于被繼承脆诉,可以對(duì)個(gè)列表項(xiàng)進(jìn)行最大限度的定制。
Adapter 淺談
ArrayAdapter
ArrayAdapter(Context context, int resource, int textViewResourceId)
ArrayAdapter 三個(gè)參數(shù)說明:
- context:整個(gè)應(yīng)用的上下文
- resource:界面布局 ID坦报,代表一個(gè)布局樣式文件库说,控制列表項(xiàng)的外觀,此樣式文件只能有一個(gè) TextView片择,連 Layout 也不能有潜的;可以使用系統(tǒng)自帶的樣式文件(android.R.layout.xxx),也可以使用自定義的樣式文件(R.layout.xxx)
- textViewResourceId:列表項(xiàng)中的數(shù)據(jù)
SimpleAdapter
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
SimpleAdapter 五個(gè)參數(shù)說明:
- context:整個(gè)應(yīng)用的上下文
- data: List<? extends Map<String, ?>> 類型的集合對(duì)象字管,集合中每個(gè) Map<String, ?> 對(duì)象生成一個(gè)列表項(xiàng)
- resource:界面布局 Id啰挪,代表一個(gè)布局樣式文件,該文件作為列表項(xiàng)的組件嘲叔,控制列表項(xiàng)的外觀
- from:String[] 類型的參數(shù)亡呵,該參數(shù)決定提取 Map<String, ?> 對(duì)象中哪些 key 對(duì)應(yīng)的 value 來生成列表項(xiàng)
- to:int[] 類型的參數(shù),該參數(shù)決定使用自定義布局中的哪些 View 組件來組合成一個(gè)列表項(xiàng)(數(shù)組里面的 id 是自定義布局中各個(gè)控件的 id硫戈,順序需要與上面的 from 中的順序?qū)?yīng))
BaseAdapter
繼承 BaseAdapter 時(shí)锰什,必須重寫它的 4 個(gè)方法,具體如下:
- getCount():返回 adapter 中數(shù)據(jù)的個(gè)數(shù)丁逝,即返回列表項(xiàng)的行數(shù)
- getItem(int position):獲得相應(yīng)數(shù)據(jù)集合中特定位置的數(shù)據(jù)項(xiàng)汁胆,即返回當(dāng)前 Item 顯示的數(shù)據(jù)
- getItemId(int position):返回 Item 的 Id
- getView(int position, View convertView, ViewGroup parent):每一個(gè) Item 項(xiàng)創(chuàng)建時(shí)被調(diào)用(即每一次 Item 從屏幕外滑進(jìn)屏幕內(nèi)的時(shí)候調(diào)用,或者程序剛開始的時(shí)候創(chuàng)建第一屏 Item 的時(shí)候調(diào)用)
- position:界面上 Item 的 Id
- convertView:展示在界面上的一個(gè) Item霜幼,可以用來緩存布局
- parent:加載 XML 視圖時(shí)使用
Adapter 和 ViewAdapter 結(jié)合使用
Spinner (列表選擇框)
Spinner嫩码,顧名思義,當(dāng)需要用戶選擇的時(shí)候罪既,可以提供一個(gè)列表將所有可選項(xiàng)列出來铸题,供用戶選擇。
Spinner 的列表項(xiàng)數(shù)據(jù)的獲取方法有兩種琢感,一是直接在 XML 布局文件中為 android:entries 屬性指定數(shù)組作為數(shù)據(jù)源丢间,二是在代碼中通過 AdapterView 的 setAdapter(adapter) 設(shè)置。
1. 在 XML 布局中指定數(shù)組作為數(shù)據(jù)源
- 在 values 文件下新建一個(gè) arrays.xml 文件驹针,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="phone_brand">
<item>HTC</item>
<item>iPhone</item>
<item>Samsung</item>
<item>Motorola</item>
<item>Huawei</item>
<item>Nokia</item>
</string-array>
</resources>
- 在 XML 布局文件中定義一個(gè) Spinner千劈,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.spinnertest.MainActivity" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/phone_brand" />
</LinearLayout>
注: android:spinnerMode 屬性可以設(shè)置 Spinner 的樣式,當(dāng)設(shè)置為 android:spinnerMode="dropdown" 時(shí)牌捷,為下拉樣式墙牌;當(dāng)設(shè)置 android:spinnerMode="dialog" 時(shí)涡驮,為彈出選擇框樣式,此時(shí)可以添加屬性 android:prompt喜滨,為彈出的選擇框添加標(biāo)題捉捅。
A. 設(shè)置為 android:spinnerMode="dropdown",即下拉樣式
- XML 文件布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.spinnertest.MainActivity" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/phone_brand"
android:spinnerMode="dropdown" />
</LinearLayout>
- 效果演示:

B. 設(shè)置為 android:spinnerMode="dialog"虽风,即彈出選擇框樣式
- XML 文件布局:
- ```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.spinnertest.MainActivity" >
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/phone_brand"
android:spinnerMode="dialog"
android:prompt="@string/select_phone_brand" />
</LinearLayout>
上面代碼中棒口,android:prompt 屬性用于設(shè)置彈出選擇框的標(biāo)題。注意辜膝,此處只能引用字符串變量已球,而不能直寫標(biāo)題的內(nèi)容篡诽,否則編譯時(shí)會(huì)出錯(cuò)竟终。
-
效果演示:
2. 在代碼中通過 AdapterView 的 setAdapter(adapter) 設(shè)置
- XML 文件布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.spinnertest.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="請(qǐng)選擇城市:" />
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
- Java 代碼:
public class MainActivity extends AppcompatActivity {
private String[] location = { "北京", "廣東", "浙江", "四川", "海南", "福建" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 從布局中獲取到 Spinner 的實(shí)例
Spinner spinner = (Spinner) findViewById(R.id.spinner);
// 2. 創(chuàng)建一個(gè) ArrayAdapter 的對(duì)象卧檐,并進(jìn)行初始化
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, location);
// 3. 為 Spinner 設(shè)置 Adapter
spinner.setAdapter(arrayAdapter);
}
}
- 效果演示:

上面的代碼中我們使用了 ArrayAdapter,實(shí)際上也可以使用其它 Adapter忱辅,如 SimpleAdapter七蜘、擴(kuò)展 BaseAdapter 等,道理是一樣的墙懂。
##GridView
> 1. GridView橡卤,即網(wǎng)格視圖,用于在界面上按行损搬、列分布的方式來顯示多個(gè)組件;
> 2. GridView 默認(rèn)為一列碧库,如果想要顯示多列,需要在 XML 布局中為屬性 android:numColumns 或在代碼中 使用方法 setNumColumns(int) 指定列數(shù)巧勤,而行數(shù)是動(dòng)態(tài)改變的嵌灰,無需指定。
**值得注意的是踢关,雖然 GridView 和 ListView 一樣繼承了 AbsListView,但 GridView 并沒有 android:entries 屬性粘茄,所以我們不能在 XML 布局中為 GridView 指定數(shù)據(jù)源签舞,只能在代碼中通過 AdapterView 的 setAdapter(adapter) 設(shè)置。**
下面是我們要達(dá)到的效果:

**注:** 這次我們使用 SimpleAdapter 來實(shí)現(xiàn)柒瓣。
**下面我們以水果為例儒搭,圖片為水果圖片,文字為水果名稱**
1) 由于圖中有行和列芙贫,所以我們可以使用 GridView 來實(shí)現(xiàn)搂鲫,從圖中可以看出,總共有 3 列磺平。下面是 XML 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.gridviewtest.MainActivity">
<GridView
android:id="@+id/gridView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="3" />
</LinearLayout>
2) 自定義樣式文件魂仍,該文件作為列表項(xiàng)的組件拐辽,控制列表項(xiàng)的外觀:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal">
<!-- 自定義一個(gè) ImageView,用來顯示圖片 -->
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 自定義一個(gè) TextView擦酌,用來顯示文字 -->
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp" />
</LinearLayout>
3) Java 代碼:
public class MainActivity extends AppCompatActivity {
// 定義一個(gè) int 型數(shù)組俱诸,用來存放水果對(duì)應(yīng)圖片的資源 id
private int[] images = {R.drawable.apple_pic, R.drawable.banana_pic, R.drawable.cherry_pic,
R.drawable.grape_pic, R.drawable.mango_pic, R.drawable.orange_pic, R.drawable.pear_pic,
R.drawable.pineapple_pic, R.drawable.strawberry_pic};
// 定義一個(gè) String 類型的數(shù)組,用來存放水果的名稱
private String[] names = {"蘋果", "香蕉", "櫻桃", "葡萄", "芒果", "香橙", "雪梨", "菠蘿", "草莓"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 創(chuàng)建一個(gè) List 集合赊舶,List 集合的元素是 Map
List<Map<String, Object>> listItems = new ArrayList<Map<String,Object>>();
for(int i=0;i<names.length;i++){
// 創(chuàng)建一個(gè) Map 集合睁搭,用來存放水果圖片和水果名稱
Map<String, Object> listItem = new HashMap<String, Object>();
listItem.put("images", images[i]);
listItem.put("names", names[i]);
listItems.add(listItem);
}
// 1. 從布局中獲取到 GridView 的實(shí)例
GridView gridView = (GridView) findViewById(R.id.gridView);
// 2. 創(chuàng)建一個(gè) SimpleAdapter 的實(shí)例,并進(jìn)行初始化
SimpleAdapter simpleAdapter = new SimpleAdapter(
this, listItems, R.layout.gridview_item, new String[] {"images", "names", new int[] {R.id.fruit_image, R.id.fruit_name});
// 3. 為 GridView 設(shè)置 Adapter
gridView.setAdapter(simpleAdapter);
}
}
4) 效果演示:

上面的代碼中我們使用了 SimpleAdapter笼平,實(shí)際上也可以使用其它 Adapter园骆,如 ArrayAdapter、擴(kuò)展 BaseAdapter 等寓调,道理是一樣的锌唾。
##ListView
> ListView ,以**垂直列表**的形式顯示所有列表項(xiàng)捶牢。
**與 Spinner 類似鸠珠,ListView 的列表項(xiàng)數(shù)據(jù)的獲取方法有兩種,一是直接在 XML 布局文件中為 android:entries 屬性指定數(shù)組作為數(shù)據(jù)源秋麸,二是在代碼中通過 AdapterView 的 setAdapter(adapter) 設(shè)置渐排。**
###1. 在 XML 布局中指定數(shù)組作為數(shù)據(jù)源
1) 在 values 文件下新建一個(gè) arrays.xml 文件,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="phone_brand">
<item>HTC</item>
<item>iPhone</item>
<item>Samsung</item>
<item>Motorola</item>
<item>Huawei</item>
<item>Nokia</item>
</string-array>
</resources>
2) 在 XML 布局文件中定義一個(gè) ListView灸蟆,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.listviewtest.MainActivity" >
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/phone_brand" />
</LinearLayout>
3) 效果演示:

###2. 在代碼中通過 AdapterView 的 setAdapter(adapter) 設(shè)置
下面是我們要達(dá)到的效果:

**注:** 這次我們使用自定義 Adapter驯耻。
**下面我們?nèi)匀灰运麨槔瑘D片為水果圖片炒考,文字為水果名稱**
1) 首先定義我們自己的 Adapter可缚,從圖中可以看出,Adapter 中要有文字和圖片斋枢,所以我們可以用一個(gè) List<String> 類型的集合和 List<Integer> 類型的集合來存放文字和圖片(因?yàn)樵?R.java 文件中圖片資源的 id 是 int 類型的)帘靡。自定義的 Adapter 如下:
public class MyListViewAdapter extends BaseAdapter {
private Context mContext;
private int mResource;
private List<Integer> mImage;
private List<String> mText;
public MyListViewAdapter(Context context, int resource, List<Integer> image, List<String> text) {
mContext = context;
mResource = resource;
mText = text;
mImage = image;
}
@Override
public int getCount() {
return mText.size();
}
@Override
public Object getItem(int position) {
return mText.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// LayoutInflater,布局加載器瓤帚,用來加載從外部傳進(jìn)來的布局
convertView = LayoutInflater.from(mContext).inflate(mResource, null);
// 注意描姚,外部傳進(jìn)來的布局文件中必須要有 id 為 fruit_image 的 ImageView 和 id 為 fruit_name 的 TextView,
// 否則會(huì)出現(xiàn) NullPointerException 錯(cuò)誤戈次,即空指針
ImageView iv = (ImageView) convertView.findViewById(R.id.fruit_image);
TextView tv = (TextView) convertView.findViewById(R.id.fruit_name);
iv.setImageResource(mImage.get(position));
tv.setText(mText.get(position));
return convertView;
}
}
2) XML 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="net.monkeychan.listviewtest.MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
3) 自定義樣式文件轩勘,該文件作為列表項(xiàng)的組件,控制列表項(xiàng)的外觀:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/fruit_image"
android:layout_width="36dp"
android:layout_height="36dp" />
<TextView
android:id="@+id/fruit_name"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"/>
</LinearLayout>
4) Java 代碼:
public class MainActivity extends AppCompatActivity {
// 定義一個(gè) int 型數(shù)組怯邪,用來存放水果圖片的 id绊寻,圖片文件放在 drawable 文件夾下
private int[] images = {R.drawable.apple_pic,
R.drawable.banana_pic, R.drawable.cherry_pic,
R.drawable.grape_pic, R.drawable.mango_pic,
R.drawable.orange_pic, R.drawable.pear_pic,
R.drawable.pineapple_pic, R.drawable.strawberry_pic,
R.drawable.watermelon_pic};
// 定義一個(gè)String 類型數(shù)組,用來存放水果名稱
private String[] names = {"蘋果", "香蕉", "櫻桃", "葡萄", "芒果", "香橙",
"雪梨", "菠蘿", "草莓", "西瓜"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 創(chuàng)建一個(gè) List<Integer> 集合,用來存放水果圖片
List<Integer> imagesList = new ArrayList<>();
for (int i = 0; i < images.length; i++) {
imagesList.add(images[i]);
}
// 創(chuàng)建一個(gè) List<String> 集合澄步,用來存放水果名稱
List<String> namesList = new ArrayList<>();
for (int i = 0; i < names.length; i++) {
namesList.add(names[i]);
}
// 1. 從布局中獲取到 ListView 的實(shí)例
ListView listView = (ListView) findViewById(R.id.listView);
// 2. 創(chuàng)建一個(gè) MyListViewAdapter 的對(duì)象冰蘑,并進(jìn)行初始化
MyListViewAdapter myListViewAdapter = new MyListViewAdapter(this, R.layout.listview_item, imagesList, namesList);
// 3. 為 ListView 設(shè)置 Adapter
listView.setAdapter(myListViewAdapter);
}
}
5) 效果演示:

上面的代碼中我們使用了自定義 Adapter,實(shí)際上也可以使用其它 Adapter驮俗,如 ArrayAdapter懂缕、擴(kuò)展 BaseAdapter 等,道理是一樣的王凑。
##自定義 Adapter 的優(yōu)化——提升 AdapterView 的運(yùn)行效率
以上面的 ListView 的為例搪柑,我們自定義了一個(gè) Adapter,來看看我們的 getView() 方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// LayoutInflater索烹,布局加載器工碾,用來加載從外部傳進(jìn)來的布局
convertView = LayoutInflater.from(mContext).inflate(mResource, null);
ImageView iv = (ImageView) convertView.findViewById(R.id.fruit_image);
TextView tv = (TextView) convertView.findViewById(R.id.fruit_name);
iv.setImageResource(mImage.get(position));
tv.setText(mText.get(position));
return convertView;
}
前面我們說過,getView() 方法是每一個(gè) Item 項(xiàng)創(chuàng)建時(shí)被調(diào)用百姓,并且在 getView() 方法中渊额,我們每次都將布局重新加載了一遍。當(dāng)我們的 Item 項(xiàng)數(shù)目超出屏幕可顯示范圍時(shí)垒拢,而我們又來回滑動(dòng) ListView 時(shí)旬迹,其實(shí)是多個(gè) Item 項(xiàng)在被反復(fù)創(chuàng)建、同一個(gè)布局在被反復(fù)加載求类,而每一次創(chuàng)建 Item 項(xiàng)奔垦、加載布局時(shí),就會(huì)消耗一次系統(tǒng)資源尸疆,這對(duì)系統(tǒng)來說是極大的開銷椿猎。當(dāng)多次滑動(dòng)過后,有可能造成滑動(dòng)的過程中出現(xiàn)卡頓寿弱,造成的用戶體驗(yàn)非常不好犯眠。那么,有沒有這種可能症革,將之前已經(jīng)創(chuàng)建好的 Item 項(xiàng)和已經(jīng)加載過的布局緩存起來筐咧,當(dāng)再次使用時(shí),只須從緩存中拿出來使用噪矛,而不用再次創(chuàng)建呢量蕊?這就是下面我們要做的。
1. 首先摩疑,我們要對(duì)布局進(jìn)行緩存:
我們可以在調(diào)用 getView() 方法時(shí)進(jìn)行判斷危融,如果緩存中不存在布局畏铆,我們才去加載布局雷袋,否則不加載。getView() 方法中有一個(gè) convertView 參數(shù),這個(gè)參數(shù)用于將之前加載好的布局進(jìn)行緩存楷怒,以便進(jìn)行重用蛋勺。至此,布局緩存的問題解決了鸠删。但是抱完,在 getView() 方法中,我們每次都會(huì)調(diào)用 findViewById() 方法來獲取控件的實(shí)例刃泡,這部分還可以優(yōu)化巧娱;
2. 其次,對(duì)控件實(shí)例進(jìn)行緩存:
我們可以定義這樣一個(gè)類烘贴,它負(fù)責(zé)緩存控件的實(shí)例禁添,我們給這個(gè)類取名叫 ViewHolder,當(dāng) convertView 為空(即緩存中不存在布局)時(shí)桨踪,創(chuàng)建一個(gè) ViewHolder 對(duì)象老翘,將控件的實(shí)例存儲(chǔ)在 ViewHolder 中。
**下面是改寫后的自定義 Adapter:**
public class MyListViewAdapter extends BaseAdapter {
private Context mContext;
private int mResource;
private List<Integer> mImage;
private List<String> mText;
public MyListViewAdapter(Context context, int resource, List<Integer> image, List<String> text) {
mContext = context;
mResource = resource;
mText = text;
mImage = image;
}
@Override
public int getCount() {
return mText.size();
}
@Override
public Object getItem(int position) {
return mText.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
// 判斷 convertView 是否為空
if (convertView == null) {
// LayoutInflater锻离,布局加載器铺峭,用來加載從外部傳進(jìn)來的布局
convertView = LayoutInflater.from(mContext).inflate(mResource, null);
// 創(chuàng)建 ViewHolder 的對(duì)象
viewHolder = new ViewHolder();
// 將控件實(shí)例存儲(chǔ)在 ViewHolder 中
viewHolder.iv = (ImageView) convertView.findViewById(R.id.fruit_image);
viewHolder.tv = (TextView) convertView.findViewById(R.id.fruit_name);
// 將 ViewHolder 存儲(chǔ)在 convertView 中,即緩存布局
convertView.setTag(viewHolder);
} else {
// 重新獲取 ViewHolder
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.iv.setImageResource(mImage.get(position));
viewHolder.tv.setText(mText.get(position));
return convertView;
}
// 創(chuàng)建一個(gè)內(nèi)部類 ViewHolder汽纠,用來緩存控件實(shí)例
class ViewHolder {
ImageView iv;
TextView tv;
}
}
##總結(jié)
**AdapterView 和 Adapter 結(jié)合使用的步驟:**
1. 從布局中獲取到 AdapterView 的實(shí)例卫键,即 findViewById();
2. 創(chuàng)建適合的 Adapter 對(duì)象疏虫,并進(jìn)行初始化(根據(jù) Adapter 的構(gòu)造方法的參數(shù)列表傳入對(duì)應(yīng)的參數(shù)類型)永罚;
3. 為 AdapterView 設(shè)置 Adapter;
4. 當(dāng)自定義 Adapter 時(shí)卧秘,應(yīng)注意優(yōu)化方面的問題呢袱。
----
參考資料:
- [《瘋狂 Android 講義》- 李剛](http://www.crazyit.org)
- [《第一行代碼——Android》- 郭霖](http://guolin.tech)
- [Android ArrayAdapter 詳解 - 彭香香的專欄](http://blog.csdn.net/nairuohe/article/details/6457300)
- [Android ListView使用BaseAdapter與ListView的優(yōu)化](http://www.open-open.com/lib/view/open1339485728006.html)