BaseAdapter的使用(筆記)
適配器模式的應用:
1.降低程式耦合性
2.容易擴充
BaseAdapter
ListView的顯示與緩衝機制:需要才顯示,顯示完就被會受到緩衝。
BaseAdapter基本結構
--public int getCount(); 適配器中資料集中資料的個數
--public Object getItem(int position):擷取資料集中與指定索引對應的資料項目
--public long getItem(int position):擷取指定行對應的ID
--public View getView(int position, ViewconverView, ViewGroup parent):擷取每一個Item的顯示內容
第一步: 建立布局檔案 activity_main.xml 建立好了一個簡單的listView
建立item布局檔案item.xml,其中有一個ImageView 兩個 TextView
activity_main.xml
item.xml
效果
第二步:建立一個Bean對象ItemBean,封裝item中顯示的內容,在首頁面MainActivity.java裡面建立資料來源
ItemBean.java
public class ItemBean {public int ItemImageResid;public String Itemtitle;public String ItemContent;public ItemBean(int itemImageResid, String itemtitle, String itemContent) {super();ItemImageResid = itemImageResid;Itemtitle = itemtitle;ItemContent = itemContent;}}
MainActivity.java
package com.example.sr;import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List itemBeanList = new ArrayList(); for(int i = 0; i < 20; i++){ itemBeanList.add(new ItemBean(R.drawable.ic_launcher, "我是標題"+i, "我是內容"+i)); } }}
第三步:建立MyAdapter類,繼承自BaseAdapter , 重寫裡面的方法,實現適配器
MyAdapter.java
package com.example.sr;import java.util.List;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;public class MyAdapter extends BaseAdapter {private List mList;public MyAdapter(List list){ //資料來源與適配器進行了關聯mList = list;}@Overridepublic int getCount() { //返回ListView需要顯示的資料量// TODO Auto-generated method stubreturn mList.size();}@Overridepublic Object getItem(int position) {//擷取資料集中與指定索引對應的資料項目// TODO Auto-generated method stubreturn mList.get(position);}@Overridepublic long getItemId(int position) {//擷取指定行對應的ID// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2) {//返回每一項的顯示內容// TODO Auto-generated method stubreturn null;}}
上面最主要的是getView方法,還沒有實現,下面介紹getView方法實現的三重境界
1.逗比式
MyAdapter.java
package com.example.sr;import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;public class MyAdapter extends BaseAdapter {private List mList;private LayoutInflater minflater;//布局裝載器對象,用於把xml布局檔案轉化為viewpublic MyAdapter(Context context, List list){ //資料來源與適配器進行了關聯mList = list;minflater = LayoutInflater.from(context);//context要使用當前的Adapter的介面對象}@Overridepublic int getCount() { //返回ListView需要顯示的資料量// TODO Auto-generated method stubreturn mList.size();}@Overridepublic Object getItem(int position) {//擷取資料集中與指定索引對應的資料項目// TODO Auto-generated method stubreturn mList.get(position);}@Overridepublic long getItemId(int position) {//擷取指定行對應的ID// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int postion, View convertView, ViewGroup parent) {//返回每一項的顯示內容// TODO Auto-generated method stubView view = minflater.inflate(R.layout.item, null);//第一個參數為 需要裝載到item.xml布局檔案,第二個參數通常寫nullImageView imageView = (ImageView) view.findViewById(R.id.iv_image);TextView title = (TextView)view.findViewById(R.id.tv_title);TextView content = (TextView)view.findViewById(R.id.tv_content);//將資料取出來賦給這三個控制項ItemBean bean = mList.get(postion);imageView.setImageResource(bean.ItemImageResid);title.setText(bean.Itemtitle);content.setText(bean.ItemContent);return view;}}
回到MainActivity.java 建立listView與MyAdapter的聯絡
MainActivity.java
package com.example.sr;import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.widget.ListView;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); List itemBeanList = new ArrayList(); for(int i = 0; i < 20; i++){ itemBeanList.add(new ItemBean(R.drawable.ic_launcher, "我是標題"+i, "我是內容"+i)); } //建立listView與MyAdapter的聯絡 ListView listView = (ListView) findViewById(R.id.lv_main); listView.setAdapter(new MyAdapter(this, itemBeanList));//第一個參數為context,第二個是資料來源 }}
至此,運行程式,發現listView可以顯示我們想要的東西了。
為什麼式逗比式呢?listView有緩衝機制,但是在getView無視了緩衝機制,都通過建立一個新的view去設定空間,效率及其低下,完全沒有利用到listView的緩衝機制。
2. 普通式
修改getView方法
@Overridepublic View getView(int postion, View convertView, ViewGroup parent) {//返回每一項的顯示內容// TODO Auto-generated method stub//逗比式開始----------//View view = minflater.inflate(R.layout.item, null);//第一個參數為 需要裝載到item.xml布局檔案,第二個參數通常寫null/*ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);TextView title = (TextView)view.findViewById(R.id.tv_title);TextView content = (TextView)view.findViewById(R.id.tv_content);//將資料取出來賦給這三個控制項ItemBean bean = mList.get(postion);imageView.setImageResource(bean.ItemImageResid);title.setText(bean.Itemtitle);content.setText(bean.ItemContent);*///逗比式結束-----------//普通式,參數中已經有了一個converView,考慮是否緩衝過了,如果緩衝過了,可以直接使用if(convertView == null){convertView = minflater.inflate(R.layout.item, null);}ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);TextView title = (TextView)convertView.findViewById(R.id.tv_title);TextView content = (TextView)convertView.findViewById(R.id.tv_content);ItemBean bean = mList.get(postion);imageView.setImageResource(bean.ItemImageResid);title.setText(bean.Itemtitle);content.setText(bean.ItemContent);return convertView;}
利用了ListView的緩衝特性,如果沒有緩衝才建立新的View,算入門,但是findViewById依然會浪費大量時間
3. 文藝式(最好的)
建立了一個內部類 ViewHolder ,它與view相關聯,並緩衝item的組件,這樣給item設定內容的時候,不用再去findviewById, 直接在ViewHolder裡面取出來就行了。
@Overridepublic View getView(int postion, View convertView, ViewGroup parent) {//返回每一項的顯示內容// TODO Auto-generated method stub//逗比式開始----------//View view = minflater.inflate(R.layout.item, null);//第一個參數為 需要裝載到item.xml布局檔案,第二個參數通常寫null/*ImageView imageView = (ImageView) view.findViewById(R.id.iv_image);TextView title = (TextView)view.findViewById(R.id.tv_title);TextView content = (TextView)view.findViewById(R.id.tv_content);//將資料取出來賦給這三個控制項ItemBean bean = mList.get(postion);imageView.setImageResource(bean.ItemImageResid);title.setText(bean.Itemtitle);content.setText(bean.ItemContent);*///逗比式結束-----------//普通式,參數中已經有了一個converView,考慮是否緩衝過了,如果緩衝過了,可以直接使用---------/* if(convertView == null){convertView = minflater.inflate(R.layout.item, null);}ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_image);TextView title = (TextView)convertView.findViewById(R.id.tv_title);TextView content = (TextView)convertView.findViewById(R.id.tv_content);ItemBean bean = mList.get(postion);imageView.setImageResource(bean.ItemImageResid);title.setText(bean.Itemtitle);content.setText(bean.ItemContent);return convertView;*///普通式結束-----------------ViewHolder viewHolder;if(convertView == null){viewHolder = new ViewHolder();convertView = minflater.inflate(R.layout.item, null);viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);//把控制項儲存在ViewHolder中viewHolder.title = (TextView)convertView.findViewById(R.id.tv_title);viewHolder.content = (TextView)convertView.findViewById(R.id.tv_content);convertView.setTag(viewHolder);//進行關聯,把它的控制項儲存在viewHolder中,避免了findviewbyid去執行個體化}else{viewHolder = (ViewHolder)convertView.getTag();}ItemBean bean = mList.get(postion);viewHolder.imageView.setImageResource(bean.ItemImageResid);viewHolder.title.setText(bean.Itemtitle);viewHolder.content.setText(bean.ItemContent);return convertView;}class ViewHolder{ //首先建立內部類public ImageView imageView;public TextView title;public TextView content;}
不僅利用了ListView的緩衝,更通過ViewHolder類來實現顯示資料的視圖的緩衝,避免多次通過findViewById尋找控制項,這是最好的方法。
總結:
ViewHolder最佳化BaseAdapter的思路
--建立Bean對象,用於封裝資料
--建立MyAdapter(繼承BaseAdapter)在構造方法中初始化用於映射的資料List
--建立ViewHolder類,建立布局映射關係
--判斷ConverView,為空白則建立,並設定Tag,否則通過tag來取出ViewHolder
--給ViewHolder中的控制項設定資料