适配器模式的应用:
1.减少程序耦合性
2.easy扩展
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
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ListView android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/iv_image" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/ic_launcher"/> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="30dp" android:layout_toEndOf="@+id/iv_image" android:text="Title" android:gravity="center" android:textSize="25sp"/> <TextView android:id="@+id/tv_content" android:layout_width="match_parent" android:layout_height="30dp" android:layout_below="@+id/tv_title" android:layout_toRightOf="@+id/iv_image" android:text="content" android:gravity="center_vertical" android:textSize="20sp"/> </RelativeLayout>
效果如图:
第二步:创建一个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; } }
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<ItemBean> itemBeanList = new ArrayList<ItemBean>(); for(int i = 0; i < 20; i++){ itemBeanList.add(new ItemBean(R.drawable.ic_launcher, "我是标题"+i, "我是内容"+i)); } } }
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<ItemBean> mList; public MyAdapter(List<ItemBean> list){ //数据源与适配器进行了关联 mList = list; } @Override public int getCount() { //返回ListView须要显示的数据量 // TODO Auto-generated method stub return mList.size(); } @Override public Object getItem(int position) {//获取数据集中与指定索引相应的数据项 // TODO Auto-generated method stub return mList.get(position); } @Override public long getItemId(int position) {//获取指定行相应的ID // TODO Auto-generated method stub return position; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) {//返回每一项的显示内容 // TODO Auto-generated method stub return 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<ItemBean> mList; private LayoutInflater minflater;//布局装载器对象。用于把xml布局文件转化为view public MyAdapter(Context context, List<ItemBean> list){ //数据源与适配器进行了关联 mList = list; minflater = LayoutInflater.from(context);//context要使用当前的Adapter的界面对象 } @Override public int getCount() { //返回ListView须要显示的数据量 // TODO Auto-generated method stub return mList.size(); } @Override public Object getItem(int position) {//获取数据集中与指定索引相应的数据项 // TODO Auto-generated method stub return mList.get(position); } @Override public long getItemId(int position) {//获取指定行相应的ID // TODO Auto-generated method stub return position; } @Override public 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); 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<ItemBean> itemBeanList = new ArrayList<ItemBean>(); 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方法
<span style="white-space:pre"> </span>@Override public 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里面取出来即可了。
<span style="white-space:pre"> </span>@Override public 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中的控件设置数据
源码下载:BaseAdapter的使用