1. 程式人生 > >Android學習(十一)—— Android介面卡

Android學習(十一)—— Android介面卡

Android介面卡

安卓的介面卡在我看來是一個非常重要的知識點,面對形式相同但資料來源較多的情況時,介面卡是一個比較好的解決方法。資料介面卡是建立了資料來源與控制元件之間的適配關係,將資料來源轉換為控制元件能夠顯示的資料格式,從而將資料的來源與資料的顯示進行解耦,降低程式的耦合性。
這篇文章就說一下如何實現介面卡。

首先說一下ListView的顯示和快取機制

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

然後來看一下實現方法

效果圖

activity_main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:id="@+id/container"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:orientation
="vertical"> 7 8 <ListView 9 android:id="@+id/lv_main" 10 android:layout_width="match_parent" 11 android:layout_height="match_parent" 12 /> 13 14 </LinearLayout>

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

 1 <?xml version="1.0" encoding="utf-8"?>
2 <RelativeLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <ImageView 8 android:id="@+id/iv_image" 9 android:src="@mipmap/ic_launcher" 10 android:layout_width="60dp" 11 android:layout_height="60dp"/> 12 <TextView 13 android:id="@+id/tv_title" 14 android:layout_width="match_parent" 15 android:layout_height="30dp" 16 android:layout_toEndOf="@id/iv_image" 17 android:text="Title" 18 android:gravity="center" 19 android:textSize="25sp"/> 20 21 <TextView 22 android:id="@+id/tv_content" 23 android:layout_width="match_parent" 24 android:layout_height="wrap_content" 25 android:layout_toEndOf="@id/iv_image" 26 android:layout_below="@id/tv_title" 27 android:text="Content" 28 android:gravity="center" 29 android:textSize="20sp"/> 30 31 </RelativeLayout>

ItemBean.java(資料來源)

 1 public class ItemBean {
 2 
 3     public int itemImageResId;  //影象資源ID
 4     public String itemTitle;     //標題
 5     public String itemContent;   //內容
 6 
 7     public ItemBean(int itemImageResId, String itemTitle, String itemContent) {
 8         this.itemImageResId = itemImageResId;
 9         this.itemTitle = itemTitle;
10         this.itemContent = itemContent;
11     }
12 
13 }

MainActivity.java

 1 public class MainActivity extends Activity {
 2 
 3     ListView mListView ;
 4     @Override
 5     protected void onCreate(Bundle savedInstanceState) {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.activity_main);
 8 
 9         List<ItemBean> itemBeanList = new ArrayList<>();
10         for (int i = 0;i < 20; i ++){
11             itemBeanList.add(new ItemBean(R.mipmap.ic_launcher, "標題" + i, "內容" + i));
12         }
13         mListView = (ListView) findViewById(R.id.lv_main);
14         //設定ListView的資料介面卡
15         mListView.setAdapter(new MyAdapter(this,itemBeanList));
16     }
17 
18 }
MyAdapter.java
此方式不僅利用了ListView的快取機制,而且使用ViewHolder類來實現顯示資料檢視的快取,避免多次呼叫findViewById來尋找控制元件,以達到優化程式的目的。
所以,大家在平時的開發中應當儘量使用這種方式進行getView的實現。
 1 public class MyAdapter extends BaseAdapter {
 2 
 3     private List<ItemBean> mList;//資料來源
 4     private LayoutInflater mInflater;//佈局裝載器物件
 5 
 6     // 通過構造方法將資料來源與資料介面卡關聯起來
 7     // context:要使用當前的Adapter的介面物件
 8     public MyAdapter(Context context, List<ItemBean> list) {
 9         mList = list;
10         mInflater = LayoutInflater.from(context);
11     }
12 
13     @Override
14     //ListView需要顯示的資料數量
15     public int getCount() {
16         return mList.size();
17     }
18 
19     @Override
20     //指定的索引對應的資料項
21     public Object getItem(int position) {
22         return mList.get(position);
23     }
24 
25     @Override
26     //指定的索引對應的資料項ID
27     public long getItemId(int position) {
28         return position;
29     }
30 
31     @Override
32     //返回每一項的顯示內容
33     public View getView(int position, View convertView, ViewGroup parent) {
34         ViewHolder viewHolder;
35         //如果view未被例項化過,快取池中沒有對應的快取
36         if (convertView == null) {
37             viewHolder = new ViewHolder();
38             // 由於我們只需要將XML轉化為View,並不涉及到具體的佈局,所以第二個引數通常設定為null
39             convertView = mInflater.inflate(R.layout.item_lv, null);
40 
41             //對viewHolder的屬性進行賦值
42             viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
43             viewHolder.title = (TextView) convertView.findViewById(R.id.tv_title);
44             viewHolder.content = (TextView) convertView.findViewById(R.id.tv_content);
45 
46             //通過setTag將convertView與viewHolder關聯
47             convertView.setTag(viewHolder);
48         }else{//如果快取池中有對應的view快取,則直接通過getTag取出viewHolder
49             viewHolder = (ViewHolder) convertView.getTag();
50         }
51         // 取出bean物件
52         ItemBean bean = mList.get(position);
53 
54         // 設定控制元件的資料
55         viewHolder.imageView.setImageResource(bean.itemImageResId);
56         viewHolder.title.setText(bean.itemTitle);
57         viewHolder.content.setText(bean.itemContent);
58 
59         return convertView;
60     }
61     // ViewHolder用於快取控制元件,三個屬性分別對應item佈局檔案的三個控制元件
62     class ViewHolder{
63         public ImageView imageView;
64         public TextView title;
65         public TextView content;
66     }
67 
68 }

ViewHolder優化BaseAdapter的整體步驟:

  1. 建立bean物件,用於封裝資料。
  2. 在構造方法中初始化的資料List。
  3. 建立ViewHolder類,建立佈局對映關係。
  4. 判斷convertView,為空則建立,並設定tag,不為空則通過tag取出ViewHolder。
  5. 給ViewHolder的控制元件設定資料。