android開發中的BaseAdapter之理解(引用自網絡,總結的很好,謝謝)

  android中的適配器(Adapter)是數據與視圖(View)之間的橋樑,用於對要顯示的數據進行處理,並通過綁定到組件進行數據的顯示。

  BaseAdapter是Android應用程序中經常用到的基礎數據適配器的基類,它實現了Adapter接口。其主要用途是將一組數據傳到像ListView、Spinner、Gallery及GridView等UI顯示組件進行顯示。我們經常使用的ListView 的adapter(即SimpleAdapter),是繼承自BaseAdapter基類的。BaseAdapter是一個基類,沒有實現綁定數據的功能。而SimpleAdapter實現了基本控件的綁定,如TextView,Button,ImageView等。並已經爲我們實現好了數據優化工作。

  這些適配器使用相同組件動態綁定數據的方式進行優化。爲什麼需要優化呢?因爲如果我們有上億個(較多個)項目要顯示怎麼辦?爲每個項目創建一個新視圖?這不可能,因爲內存有限制。實際上Android爲你緩存了視圖。Android中有個叫做Recycler的構件,下圖是他的工作原理:

  如果你有10億個項目(item),其中只有可見的項目存在內存中,其他的在Recycler中。其實我的理解Recyler就是一個隊列,用來存儲不在屏幕範圍內的item,如果item滾出屏幕範圍,那麼就入隊,這裏的滾出是完全滾出,即邊界等也要完全滾出。如果新的item要滾進來,那麼android系統的framework就會查看Recyler是否含有可以重複使用的View,如果有那麼就重新設置該View 的數據源,然後顯示,即出隊。那麼這麼多的item其實只需要佔用一定空間的內存,這個內存大小是多少呢?我的感覺是手機屏幕所包含的item的個數,再加上1,然後乘以每個item佔用的內存。但是最後我發現是加上2.可能是爲了使得緩存更大吧。。。。但是爲什麼加上2,大家應該理解,如果你不理解,那你就把滾動list的過程好好想一想。那個隊列無非就是一個緩存罷了,因爲我們的目的是通過那個緩存來重複使用那些已經創建的View。

  使用BaseAdapter的話需要重載四個方法,這些方法分別是getView()、getCount()、getItem()和getItemId(),其中getView()最爲重要。那麼getView函數爲什麼重要呢?因爲它是用來刷新它所在的ListView的。它在什麼時候調用的呢?就是在每一次item從屏幕外滑進屏幕內的時候,或者程序剛開始的時候創建第一屏item的時候。下面分別對這幾個函數進行一個介紹:

  1. getView()

    先看看官方API的解釋: 

public abstract View getView (int position, View convertView, ViewGroup parent)

Since: API Level 1

Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file. When the View is inflated, the parent View (GridView, ListView...) will apply default layout parameters unless you use inflate(int, android.view.ViewGroup, boolean) to specify a root view and to prevent attachment to the root.

Parameters

position The position of the item within the adapter's data set of the item whose view we want.
convertView The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount() and getItemViewType(int)).
parent The parent that this view will eventually be attached to

Returns

  • A View corresponding to the data at the specified position.

  position是指當前dataset的位置,通過getCount和getItem來使用。如果list向下滑動的話那麼就是最低端的item的位置,如果是向上滑動的話那就是最上端的item的位置。convert是指可以重用的視圖,即剛剛出隊的視圖(在上面已經重點講過)。parent應該就是顯示數據的視圖(如ListView、GridView等)。

  2. getCount()

    作用:主要是獲得項目(Item)的數量。    

    官方API:    

    int getCount()

      How many items are in the data set represented by this Adapter. 

   返回:

    Count of items.

  3.getItem()

    作用:主要是獲得當前選項。注意返回值類型

    官方API:    

     Object getItem(int position)

       Get the data item associated with the specified position in the data set.

   參數:

  position - Position of the item whose data we want within the adapter's data set.

  返回:

  The data at the specified position.

  4. getItemId()

    作用:主要是獲得當前選項的ID。

    官方API:    

    long getItemId(int position)

     Get the row id associated with the specified position in the list. 

  參數:

  position - The position of the item within the adapter's data set whose row id we want.

  返回:

  The id of the item at the specified position.

  爲了更好的理解,下面給出個一個實際的BaseAdapter使用方法(該完整例子可參考明日科技Android從入門到精通第五章例程5.9):

複製代碼

 1 public class MainActivity extends Activity {
 2 
 3     public int[] imageId = new int[] { R.drawable.img01, R.drawable.img02,
 4             R.drawable.img03, R.drawable.img04, R.drawable.img05,
 5             R.drawable.img06, R.drawable.img07, R.drawable.img08,
 6             R.drawable.img09, R.drawable.img10, R.drawable.img11,
 7             R.drawable.img12}; // 定義並初始化保存圖片id的數組
 8 
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.main); // 設置該Activity使用的佈局
13         GridView gridview = (GridView) findViewById(R.id.gridView1); // 獲取GridView組件
14         BaseAdapter adapter = new BaseAdapter() {
15             @Override
16             public View getView(int position, View convertView, ViewGroup parent) {
17                 ImageView imageview; // 聲明ImageView的對象
18                 if (convertView == null) {//判斷recycler中是否有可用的View
19                     imageview = new ImageView(MainActivity.this); // 實例化ImageView的對象
20                     /************* 設置圖像的寬度和高度 ******************/
21                     imageview.setAdjustViewBounds(true);
22                     imageview.setMaxWidth(180);
23                     imageview.setMaxHeight(135);
24                     /**************************************************/
25                     imageview.setPadding(5, 5, 5, 5); // 設置ImageView的內邊距
26                 } else {
27                     imageview = (ImageView) convertView;
28                 }
29                 imageview.setImageResource(imageId[position]); // 爲ImageView設置要顯示的圖片,即設置數據源
30                 return imageview; // 返回ImageView
31             }
32 
33             /*
34              * 功能:獲得當前選項的ID
35              */
36             @Override
37             public long getItemId(int position) {
38                 return position;
39             }
40 
41             /*
42              * 功能:獲得當前選項
43              */
44             @Override
45             public Object getItem(int position) {
46                 return position;
47             }
48 
49             /*
50              * 獲得數量
51              */
52             @Override
53             public int getCount() {
54                 return imageId.length;
55             }
56         };
57 
58         gridview.setAdapter(adapter); // 將適配器與GridView關聯
59                 //爲gridView的每一項(Item)設置單擊事件監聽
60         gridview.setOnItemClickListener(new OnItemClickListener() {
61             @Override
62             public void onItemClick(AdapterView<?> parent, View view,
63                     int position, long id) {
64                 Intent intent = new Intent(MainActivity.this, BigActivity.class);
65                 Bundle bundle = new Bundle(); // 創建並實例化一個Bundle對象
66                 bundle.putInt("imgId", imageId[position]); // 保存圖片ID
67                 intent.putExtras(bundle); // 將Bundle對象添加到Intent對象中
68                 startActivity(intent); // 啓動新的Activity
69 
70             }
71         });
72 
73     }
74 }
75     

複製代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章