Android适配器Adapter的写法

在《Android第一行代码》的第三章,遇到了ListViewRecyclerView两个复杂的控件,完整的一个ListView和RecyclerView需要书写4部分代码:ListView和RecyclerView的整体布局,适配器类型类,ListView和RecyclerView的子布局,适配器。其中,适配器的写法和优化相较更为复杂。

一、ListView适配器的一般写法

public class FruitAdapter extends ArrayAdapter<Fruit> //Fruit是适配器类型类
{
   //子布局Id
   private int resourcedId;
   //构造函数,确定ListView控件的父布局和子布局,以及内容
   public FruitAdapter(Context context,int textViewResourcedId,List<Fruit> objects) 
   {
      super(context,textViewResourcedId,objects);
      resourcedId=textViewResourcedId;
   }
   @override
   public View getView(int position,View convertView,ViewGroup parent)//重写getView函数
   {
      Fruit fruit =getItem(position);
      //这个View会作为返回值
      View view=LayoutInflater.from(getContext()).inflate(resourcedId,parent,flase);
      //获取子布局控件的引用
      ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
      TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);
      //设置控件内容
      fruitName.setImageResourced(fruit.getImageId());
      fruitImage.setText(fruit.getName());
      return view;
   }
}

二、ListView适配器的优化写法

1、一般写法中ListView的运行效率是很低的,在FruitAdaptergetView()方法中,每次都将布局加载了一遍
[ View view=LayoutInflater.from(getContext()).inflate(resourcedId,parent,flase); ],这会成为性能的瓶颈。
仔细观察会发现,getView()方法中有一个View convertView参数,*这个参数用于将之前加载好的布局进行缓
存,以便之后可以进行重用。我们可以在getView()方法中进行判断,如果convertView是null,则使用LayoutInflater进行加载布局,否则直接对convertView进行重用*,代码如下:

public class FruitAdapter extends ArrayAdapter<Fruit> //Fruit是适配器类型类
{
   //子布局Id
   private int resourcedId;
   //构造函数,确定ListView控件的父布局和子布局,以及内容
   public FruitAdapter(Context context,int textViewResourcedId,List<Fruit> objects) 
   {
      super(context,textViewResourcedId,objects);
      resourcedId=textViewResourcedId;
   }
   @override
   public View getView(int position,View convertView,ViewGroup parent)//重写getView函数
   {
      Fruit fruit =getItem(position);
      //这个View会作为返回值
      View view;
      if(convertView==null)
      {
         view=LayoutInflater.from(getContext()).inflate(resourcedId,parent,flase);
      }
      else
      {
         view=convertView;
      }
      //获取子布局控件的引用
      ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
      TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);
      //设置控件内容
      fruitName.setImageResourced(fruit.getImageId());
      fruitImage.setText(fruit.getName());
      return view;
   }
}

2、经过1的优化,虽然已经不用重新去加载布局,但是每次在getView()方法中还是会调用View的findViewById方法
来获取一次控件的实例。我们可以借助一个ViewHolder来对这部分进行优化.我们新增一个内部类ViewHolder,并将控件
的实例都存放在ViewHolder里,然后调用ViewsetTag()方法,将ViewHolder对象存储在View中。当convertView不为null时,则调用ViewgetTag()方法,把ViewHolder取出。这样控件的实例都缓存在了ViewHolder里。代码如下:

public class FruitAdapter extends ArrayAdapter<Fruit> //Fruit是适配器类型类
{
   //子布局Id
   private int resourcedId;
   //构造函数,确定ListView控件的父布局和子布局,以及内容
   public FruitAdapter(Context context,int textViewResourcedId,List<Fruit> objects) 
   {
      super(context,textViewResourcedId,objects);
      resourcedId=textViewResourcedId;
   }
   @override
   public View getView(int position,View convertView,ViewGroup parent)//重写getView函数
   {
      Fruit fruit =getItem(position);
      View view;
      ViewHolder viewHolder;
      if(convertView==null)
      {
         view=LayoutInflater.from(getContext()).inflate(resourcedId,parent,flase);
         viewHolder=new ViewHolder();
         viewHolder.fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
         viewHolder.fruitName=(TextView) view.findViewById(R.id.fruit_name);
         view.setTag(viewHolder);//将viewHolder存放在view中
      }
      else
      {
         view=convertView;
         viewHolder=(ViewHolder)view.getTag();
      }
      //设置控件内容
      viewHolder.fruitName.setImageResourced(fruit.getImageId());
      viewHolder.fruitImage.setText(fruit.getName());
      return view;
   }
   class ViewHolder
   {
      ImageView fruitImage;
      TextView  fruitName;
   }
}

猜你喜欢

转载自blog.csdn.net/BruthYU/article/details/78362711