前面说到了数组适配器和简单适配器 这次来了解这个自定义适配器
1. BaseAdapter:是所有适配器类的父类,可以对列表项进行最大限度的定制
1.1 自定义适配器中的方法(有四个方法)
getCount
getView
getItem
getItemId
@Override
public int getCount() {
return data.size();//数据源的长度
}
@Override
public Object getItem(int position) {
return data.get(position);//那个文件里当前这个项资源
}
@Override
public long getItemId(int position) {
return position;//当前下标
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//实现具体操作
}
说到listView控件 它所加载的项资源就比较复杂一点 所以加载那个项资源需要用到布局解析器 然后由解析器来加载项资源.
2.LayoutInflater(布局解析器)
LayoutInflater有三种获得方式,资料中有详细介绍
用来把layout布局文件解析成一个View对象,不可以new,需要使用系统服务获得
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
具体操作写在如下class里:那边定义好了listView控件 这边获取数据源后 操作方法可展示出里面的数据
2. ListView优化
2.1 使用ConvertView重用组件
即拖动时被遮住、看不见的控件,重用它,而非每次创建一个新的对象
2.2 使用内部类ViewHolder+ConvertView.setTag()保存控件,而不用每次查找
ViewHolder(视图的持有者) 这些都已经写在里面可直接看
package com.example.t216_06;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView list_main_view;//拿到控件
private List<Book> data=new BookDao().list();//获取数据源
private MyAdapter myAdapter;//定义一个自定义适配器类来解析项资源
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list_main_view=findViewById(R.id.list_main_view);//初始化(拿到)控件
myAdapter=new MyAdapter((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE));//获取系统解析器
list_main_view.setAdapter(myAdapter);//控件绑定这个适配器
}
class MyAdapter extends BaseAdapter{//自定义适配器 要继承baseAdapter(所有适配器类的父类)
private LayoutInflater inflater;//(布局解析器)通过它来解析项资源
public MyAdapter(LayoutInflater inflater) {//有参构造
this.inflater=inflater;//上面传的给当前的这个解析器 就等于有值了
}
class viewHolder{//把所有控件定义到这个类里(优化)
ImageView image ;//通过这个视图获取里面每一个控件 图片控件
TextView title ;//获取里面每一个控件文件控件
TextView aurhor ;//获取里面每一个控件文件控件
TextView price ;//获取里面每一个控件文件控件
TextView publish;//获取里面每一个控件文件控件
TextView remark ;//获取里面每一个控件文件控件
}
@Override
public int getCount() {
return data.size();//数据源的长度
}
@Override
public Object getItem(int position) {
return data.get(position);//当前这个项资源
}
@Override
public long getItemId(int position) {
return position;//当前下标
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//即拖动时被遮住、看不见的控件,重用它,而非每次创建一个新的对象
View v=convertView;//拿到上面convertView还是空的 (优化)
if(v==null){//如果v等于空就去资源文件里创建视图 只创建一个屏幕那么多的视图就不会创建 后面直接共用前面的视图
v = inflater.inflate(R.layout.listview_item, null);//拿到项资源文件去创建视图
Log.i("post",position+"");
viewHolder holder=new viewHolder();//通过这个类获取所有控件 这样就只要设置一次
holder.aurhor=v.findViewById(R.id.tv_listviewitme_author);
holder.image=v.findViewById(R.id.iv_listviewitem_image);
holder.title=v.findViewById(R.id.tv_listviewitme_title);
holder.price=v.findViewById(R.id.tv_listviewitme_price);
holder.publish=v.findViewById(R.id.tv_listviewitme_publish);
holder.remark=v.findViewById(R.id.tv_listviewitme_remark);
v.setTag(holder);//视图绑定这个类找到的控件
}
// ImageView image = v.findViewById(R.id.iv_listviewitem_image);//通过这个视图获取里面每一个控件 图片控件
// TextView title = v.findViewById(R.id.tv_listviewitme_title);//获取里面每一个控件文件控件
// TextView aurhor = v.findViewById(R.id.tv_listviewitme_author);//获取里面每一个控件文件控件
// TextView price = v.findViewById(R.id.tv_listviewitme_price);//获取里面每一个控件文件控件
// TextView publish = v.findViewById(R.id.tv_listviewitme_publish);//获取里面每一个控件文件控件
// TextView remark = v.findViewById(R.id.tv_listviewitme_remark);//获取里面每一个控件文件控件
viewHolder tag =(viewHolder) v.getTag();//这个类来得到视图的那些控件去设置值
Book book = data.get(position);//数据源拿到当前这个项资源去展示成可看的视图
tag.image.setImageResource(book.getImage());//把控件从book拿到的设置值
tag.title.setText(book.getTitle());//然后设置下面每一个当前资源的值
tag.aurhor.setText(book.getAuthor());
tag.price.setText(book.getPrice().toString());
tag.publish.setText(book.getPublish());
tag.remark.setText(book.getRemark());
return v;
}
}
}
这个效果仅仅只是展示出来数据然后优化了加载的性能 。