鏈接AdapterView視圖和數據源的橋樑:Adapter適配器(3)

BaseAdapter是一種使用頻率較高的適配器,由於它能夠經過自定義最大程度擴展知足各類情景下的使用。咱們不只須要知道適配器的使用,進一步咱們也須要了解適配器的原理。java

問題是最好的學習方式,下面主要討論這麼幾個問題:android

Q1.ListView中每一個Item的建立app

Q2.ListView中Item的複用ide

Q3.ListView中屏幕顯示的Item與複用生成Item之間的關係post

  首先寫一個簡單的demo.學習

 1 package com.aellenlei.baseadapterdemo;
 2 
 3 import android.support.v7.app.AppCompatActivity;
 4 import android.os.Bundle;
 5 import android.widget.ListView;
 6 
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 
10 public class MainActivity extends AppCompatActivity {
11 
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16 
17         //1.findViewById
18         ListView listView = (ListView) findViewById(R.id.listView);
19 
20         //2.初始化數據源
21         List<ItemBean> list = new ArrayList<>();
22         for (int i = 0; i < 5; i++) {
23             ItemBean itemBean = new ItemBean();
24             itemBean.postion = i;
25             itemBean.title = "title " + i;
26             itemBean.content = "content " + i;
27             list.add(itemBean);
28         }
29 
30         //3.初始化適配器
31         ItemBeanAdapter itemBeanAdapter = new ItemBeanAdapter(list, getApplicationContext());
32 
33         //4.ListView綁定適配器
34         listView.setAdapter(itemBeanAdapter);
35     }
36 }
MainActivity.java
 1 package com.aellenlei.baseadapterdemo;
 2 
 3 import android.content.Context;
 4 import android.util.Log;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.BaseAdapter;
 9 import android.widget.CheckBox;
10 import android.widget.ImageView;
11 import android.widget.TextView;
12 
13 import java.util.List;
14 
15 /**
16  * User AellenLei
17  * NAME ItemBeanAdapter
18  * DATE 2016/3/7
19  */
20 public class ItemBeanAdapter extends BaseAdapter {
21 
22     private List<ItemBean> mData;
23     private Context mContext;
24 
25     public ItemBeanAdapter(List<ItemBean> mData, Context mContext) {
26         this.mData = mData;
27         this.mContext = mContext;
28     }
29 
30     @Override
31     public int getCount() {
32         return mData == null ? 0 : mData.size();
33     }
34 
35     @Override
36     public ItemBean getItem(int position) {
37         return mData.get(position);
38     }
39 
40     @Override
41     public long getItemId(int position) {
42         return position;
43     }
44 
45     @Override
46     public View getView(int position, View convertView, ViewGroup parent) {
47 
48         Log.d("msg", position + "," + getItem(position).postion + "," + getItem(position).title + ".  "
49                 + ((convertView == null) ? ("covertView = null") :
50                 (((TextView) convertView.findViewById(R.id.item_title)).getText().toString()))
51         );
52 
53 
54         View ret;
55 
56         if (convertView != null) {
57             ret = convertView;
58         } else {
59             ret = LayoutInflater.from(mContext).inflate(R.layout.item, null);
60             ViewHolder holder = new ViewHolder();
61             holder.itemIcon = (ImageView) ret.findViewById(R.id.item_icon);
62             holder.itemTitle = (TextView) ret.findViewById(R.id.item_title);
63             holder.itemContent = (TextView) ret.findViewById(R.id.item_content);
64             holder.itemDate = (TextView) ret.findViewById(R.id.item_date);
65             holder.itemChecked = (CheckBox) ret.findViewById(R.id.item_check);
66             ret.setTag(holder);
67         }
68 
69         ViewHolder viewHolder = (ViewHolder) ret.getTag();
70 
71         ItemBean itemBean = getItem(position);
72 
73         viewHolder.itemIcon.setImageResource(R.mipmap.ic_launcher);
74         viewHolder.itemTitle.setText(itemBean.title);
75         viewHolder.itemContent.setText(itemBean.content);
76         viewHolder.itemDate.setText("yyyy-MM-dd");
77         viewHolder.itemChecked.setChecked(itemBean.check);
78 
79         return ret;
80     }
81 
82     private static class ViewHolder {
83         private ImageView itemIcon;
84         private TextView itemTitle;
85         private TextView itemContent;
86         private TextView itemDate;
87         private CheckBox itemChecked;
88     }
89 }
ItemBeanAdapter
 1 package com.aellenlei.baseadapterdemo;
 2 
 3 /**
 4  * User AellenLei
 5  * NAME ItemBean
 6  * DATE 2016/3/7
 7  */
 8 public class ItemBean {
 9     public int postion;
10     public String url;
11     public String title;
12     public String content;
13     public String date;
14     public boolean check;
15 }
ItemBean
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:paddingBottom="@dimen/activity_vertical_margin"
 7     android:paddingLeft="@dimen/activity_horizontal_margin"
 8     android:paddingRight="@dimen/activity_horizontal_margin"
 9     android:paddingTop="@dimen/activity_vertical_margin"
10     tools:context=".MainActivity">
11 
12     <ListView
13         android:id="@+id/listView"
14         android:layout_width="match_parent"
15         android:layout_height="match_parent"/>
16 </RelativeLayout>
activity_main.xml
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:padding="8dp">
 6 
 7     <ImageView
 8         android:id="@+id/item_icon"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:src="@mipmap/ic_launcher"
12         android:padding="4dp"/>
13 
14     <TextView
15         android:id="@+id/item_title"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:textSize="20sp"
19         android:textStyle="bold"
20         android:layout_toRightOf="@id/item_icon"
21         android:layout_alignTop="@id/item_icon"/>
22     <TextView
23         android:id="@+id/item_content"
24         android:layout_width="wrap_content"
25         android:layout_height="wrap_content"
26         android:textSize="16sp"
27         android:layout_below="@id/item_title"
28         android:layout_toRightOf="@id/item_icon"
29         android:layout_alignBottom="@id/item_icon"/>
30 
31     <TextView
32         android:id="@+id/item_date"
33         android:layout_width="wrap_content"
34         android:layout_height="wrap_content"
35         android:layout_toRightOf="@id/item_title"
36         android:layout_alignParentRight="true"
37         android:gravity="right"/>
38     <CheckBox
39         android:id="@+id/item_check"
40         android:layout_width="wrap_content"
41         android:layout_height="wrap_content"
42         android:text="@null"
43         android:layout_below="@id/item_date"
44         android:layout_alignParentRight="true"
45         android:gravity="center"
46         android:layout_alignBottom="@id/item_content"/>
47 </RelativeLayout>
item.xml

 因爲該Demo比較簡單,不需多講相信均可以看懂。測試

 ItemBeanAdapter.java的getView方法中有這麼一句:this

  

  分別打印的是ListView中每個Item在ListView中的位置(默認從0開始,下同),該Item顯示的數據源中指定位置數據的poistion和title,convertView是否爲空若不爲空打印convertView以前顯示的title.url

 當數據源中的數據條數爲5時,Logcat的日誌:spa

  

  UI:

  

 

 當數據源中的數據條數爲10是,Logcat的日誌:

  

  UI:

  

  

  根據這兩種狀況的測試,能夠大概回答第一個問題:

Q1.ListView中每一個Item的建立

A1.Adapter第一次建立的Items的數量是由手機屏幕的大小(可測試)和數據源數據的條數來決定的,也就是屏幕實際顯示多少個Item就建立幾個item的,很少建立新的item也很多建立新的item,items數量是屏幕實際顯示數目的取整。將下面的完整結合來看,第一次建立的Item是最基本的Item,它的數量是肯定的,之後新的item不管是向上滑動出現仍是向下滑動出現都是複用第一次建立的items中的某個item。

 

Q2.ListView中Item的複用

A2:最核心的代碼就是Adapter中的getView方法,它返回的是一個已經綁定好數據的view,而系統僅僅只是將這個view在屏幕的指定位置繪製出來。

  

  代碼不是固定死的,固然你能夠有本身的寫法,可是原理老是相同的:

    A2:當ListView第一次建立一屏幕的items時,covertView始終爲null(代碼測試很容易得出),因此當covertView爲空時,就須要將第一次建立一屏幕的items的每一個item「初始化」,這裏的「初始化」是將covertView和ViewHolder綁定起來,注意不管是將covertView和ViewHolder綁定起來仍是ret和ViewHolder綁定起來,它們的本質是同樣的,最後返回值是已經與ViewHolder綁定的View視圖,當掌握了covertView的複用寫法,能夠說是基本上item的複用的寫法也掌握了。

 

    注意下面一種狀況,當ListView向上滑動,且item0徹底不見,item7和item8出現(下圖item8已經出現,只是沒有徹底顯示)的狀況:

    

    此時Logcat打印的日誌:

      

    根據以前的第一次建立items打印的日誌比較:item7仍然是新建立的,可是item8倒是複用的,item8複用的是item0(徹底根據日誌得出的)。(PS 可能此處有疑問,下面會分析)

    A2:當listView向上滑動或者是向下滑動的時候,此時可能會出現item複用的狀況(注意此時可能會出現複用的狀況,不必定或出現哦)。若covertView不爲空,就能夠以前在該covertView初始化或複用中經過getTag方法,取出與之綁定的ViewHolder,從而實現減小findViewById的時間,findViewById是須要耗費時間的,當listView顯示大量的數據,此時的findViewByid能夠極大的提升效率。

 

    最後分析總結前面的,能夠回答第三個問題:

Q3.ListView中屏幕顯示的Item與複用生成Item之間的關係

A3:ListView實際建立item的數量是由手機屏幕的大小和數據源的數據數量來決定的,準確的將這是不許確的或是錯誤的。

   ListView在整個複用過程當中本質上實際建立item的數量(這裏所指的所有是最原始最本質的item)是由手機屏幕的大小、數據源的數據數量和每一個item實際的大小來決定的(固然這裏不考慮其餘更爲負責的狀況,而是假定每一個item的大小相同)。

   用能夠惟一衡量肯定的話說是:本質上items的數量是當第一個item徹底消失後,此時Adapter總共建立的items數量,從本質上來講,這就是ListView在整個複用過程當中複用的item的數量。假如從0,1,...,n-1(n爲最原始的item數量)來看,當ListView向上滑動時,複用tem的順序是按順序複用0,1,...,n-1,每次複用一個;當ListView向下滑動時,複用的順序是按照逆序的,從n-1,n-2,..,0,也是一個一個複用的。

  固然還有更爲複雜的狀況或者說從更爲本質也就是源碼的角度分析,這裏暫不考慮,而是從一種最爲表象或者最最最基本最最簡單來分析ListView與Adapter。

相關文章
相關標籤/搜索