對於ListVie來說,資料項目的設定有很多種方式,而自訂實現BaseAdapter是最經常用的了,那麼這裡我們來講解一下自訂實現BaseAdapter的普通實現。
MainActivity.java
public class MainActivity extends AppCompatActivity { //資料來源 private List<String> data; //ListView控制項 private ListView mList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //擷取控制項ID mList = (ListView)findViewById(R.id.mList); data = new ArrayList<>(); //資料賦初值 for(int i = 0; i < 20; i ++){ data.add("資料項目"+ i); } //建立適配器 MyAdapter adapter = new MyAdapter(data); //設定適配器 mList.setAdapter(adapter); }}
MyAdapter.java
public class MyAdapter extends BaseAdapter { //資料項目 private List<String> data; public MyAdapter(List<String> data) { this.data = data; } @Override /** * 返回資料來源的長度,表示ListView的item項顯示多少個 */ public int getCount() { return data == null ? 0 : data.size(); } /** * 返回指定位置的 item 資料來源的對象,這個方法為手動調用,非設定適配器時候調用 * @param position 指定位置 * @return */ @Override public Object getItem(int position) { return data.get(position); } /** * 返回指定位置的 item的標記 id,很少使用到 * @param position 指定位置 * @return */ @Override public long getItemId(int position) { return position; } /** * Factory 方法,設定好模板,返回視圖,每個視圖是怎麼顯示出來的, 核心點,怎麼產生一個View, View 裡面怎麼 * 放置對應的內容 * @param position 當前載入的位置 * @param convertView 複用的view * @param parent listview * @return */ @Override public View getView(int position, View convertView, ViewGroup parent) { //擷取布局 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,null); //擷取布局中的TextView控制項1 TextView tv1 = (TextView) view.findViewById(R.id.mTv1); //設定控制項1的資料 tv1.setText(data.get(position)); //擷取布局中的TextView控制項2 TextView tv2 = (TextView) view.findViewById(R.id.mTv2); //設定控制項2資料 tv2.setText(data.get(position)); return view; }}
以上是普通的使用,但是這樣的效率會非常低,因為每次載入一個item都會調用getView方法,而每次都會去解析一個view布局,這樣一直解析會對記憶體的消耗特別大,所以效率會大大降低,那麼我們在此基礎上先稍微最佳化下,讓view解析次數變少一點,最基本的操作就是採用convertView複用控制項來進行操作。
這裡只需要修改getView方法中的處理:
@Override public View getView(int position, View convertView, ViewGroup parent) { Log.i("TAG", "getView: " + position); if (convertView == null) { convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null); } TextView tv1 = (TextView) convertView.findViewById(R.id.mTv1); tv1.setText(data.get(position)); TextView tv2 = (TextView) convertView.findViewById(R.id.mTv2); tv2.setText(data.get(position)); return convertView; }}
以上的處理方式相比上面的處理方式相對於上面的解析要少很多次,因為第一種實現方式是任何一個需要顯示的控制項都需要去解析一次布局,而這裡我們使用了系統給的converView複用控制項,他的基本原理是,系統會自動建立好介面顯示n個item的資料項目(比如一個介面可見的item為5個,預設建立好了5個view布局對象),儲存到converView中(這裡可以把他當成一個迴圈數組吧,他的總容量相當於是n + 1),當顯示第n + 1個的時候,他會解析一次,之後的顯示的view布局會複用自己的converView中已經存在的布局項,而不再去重新解析。簡單的畫個圖吧:
如上圖所示,相當於只解析了6次,其他的view都是複用的,所以相對於上面的實現,這樣的效率會相對高一點,不過,雖然解析的次數是少了,但是每個控制項需要findViewById還是會重複調用,而且其實每個不同對象view中的控制項id對象肯定是相同的,所以,重複的去調用又會顯得效率不高,那麼如何解決不重複findViewById呢,那就要使用到我們的最佳化布局了,關於最佳化,將在下一篇部落格中介紹。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。