ListView中怎么使用泛型适配器

这篇文章给大家介绍ListView中怎么使用泛型适配器,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1.先创建好我们今天需要的控件、源数据以及Bean类。

控件只有一个ListView

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mlv"/>
</LinearLayout>

beans方法模拟了一个假数据

privatevoidbeans(){
list=newArrayList<>();
for(inti=0;i<16;i+=4){
list.add(newStudent("同学"+i,"男",15+i,R.drawable.a,true));
list.add(newStudent("同学"+(i+1),"男",15+i,R.drawable.b,false));
list.add(newStudent("同学"+(i+2),"男",15+i,R.drawable.c,false));
list.add(newStudent("同学"+(i+3),"男",15+i,R.drawable.d,true));
}
}

这是bean类

packagezy.pers.homework_20.bean;
publicclassStudent{
privateStringname;
privateStringsex;
privateintage;
privateintimgId;
privatebooleanisOver;
publicStudent(Stringname,Stringsex,intage,intimgId,booleanisOver){
this.name=name;
this.sex=sex;
this.age=age;
this.imgId=imgId;
this.isOver=isOver;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetSex(){
returnsex;
}
publicvoidsetSex(Stringsex){
this.sex=sex;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
publicintgetImgId(){
returnimgId;
}
publicvoidsetImgId(intimgId){
this.imgId=imgId;
}
@Override
publicStringtoString(){
return"Student{"+
"name='"+name+'\''+
",sex='"+sex+'\''+
",age="+age+
",imgId="+imgId+
'}';
}
publicbooleanisOver(){
returnisOver;
}
publicvoidsetOver(booleanover){
isOver=over;
}
}

2.创建MyBaseAdapter继承BaseAdapter

publicclassMyBaseAdapter<T>extendsBaseAdapter{
@Override
publicintgetCount(){
return0;
}
@Override
publicObjectgetItem(intposition){
returnnull;
}
@Override
publiclonggetItemId(intposition){
return0;
}
@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
returnnull;
}
}

3.我们说通用适配器传入布局id和源数据,所以我们定义这两个量接收传入的数据。

privateList<Student>list;
privateintmLayRes;
publicMyBaseAdapter(List<Student>list,intmLayRes){
this.list=list;
this.mLayRes=mLayRes;
}

4.重写我们的前三个方法

前三个方法应该算是比较简单的了,

@Override
publicintgetCount(){
returnlist!=null?list.size():0;
}
@Override
publicTgetItem(intposition){
returnlist.get(position);
}
@Override
publiclonggetItemId(intposition){
returnposition;
}

第一个一个简单的判断,返回list的大小。第二个跟第三个和以前适配器一样,只是getItem的返回值写成了泛型。

5.写Viewholder类,这个是很麻烦的,我们先创建出来Viewholder,之后的方法我们一步一步添加。

publicstaticclassViewHolder{
privateSparseArray<View>mViews=newSparseArray<>();
privateContextmContext;
privateintposition;
privateintlayRes;
privateViewitemView;
privateViewHolder(Contextcontext,ViewGroupparent,intlayRes){
this.mContext=context;
this.layRes=layRes;
this.itemView=LayoutInflater.from(context).inflate(layRes,parent,false);
this.itemView.setTag(this);
}
publicstaticViewHolderbind(intposition,ViewconvertView,ViewGroupparent,intlayRes,Contextcontext){
ViewHolderholder;
if(convertView==null){
holder=newViewHolder(context,parent,layRes);
}else{
holder=(ViewHolder)convertView.getTag();
holder.itemView=convertView;
}
holder.position=position;
returnholder;
}

东西有点多,我们顺着逻辑慢慢看:

1)首先是通过单例来实现,所以我们需要一个私有化构造方法,里面有三个参数,分别是上下文,ViewGroup和布局id,这三个属性是我们必须要用到的,我们传入上下文获取inflater,把布局id传进去,然后把holder传入我们的itemView中。

这一步我们应该比较熟悉吧,我们以前是在getView中实现这一步的。

2)然后我们看下面的bind方法,他的参数有五个。其实有三个参数我们很熟悉,就是我们getView中的三个参数。在这基础上我们又添加了两个参数,布局id和上下文。

然后为了优化我们先判断当前的convertView是否为空,如果为空就新建一个Viewholder,让convertView在私有构造器中加载;如果不为空,直接通过getTag拿到。

注意我们要对holder中的两个参数进行修改,一个是itemView,一个是position。因为我们优化过后,如果convertView不为空,他里面是有之前的数据的,其他的几个属性我们不用管,但是这两个还是储存着上一个的内容。我们需要让他重新指向当前的convertView和position,给大家画一张图就很明白了:

ListView中怎么使用泛型适配器

索引什么的画的可能不准确,但是主要就是这么个意思,大家领会精神哈。

最后返回holder。

3)我们还需要返回我们加载完成的convertView,

publicViewgetItemView(){
returnitemView;
}

现在我们Viewholder基本框架写完了,我们暂时不管他了,去写getView。

6.重写方法getView:

我们刚才说了,在adapter中写一个抽象方法,然后通过回调方法,实现多类型适配,也就是说这个抽象方法是写我们给具体控件添加数据的,我们在这里面传递两个参数,一个是我们的Viewholder,另一个是对应位置的数据,类型为泛型。

publicabstractvoidbindView(ViewHolderholder,Tobj);

因为我们出现了抽象方法,所以我们的MyBaseAdapter需要变成抽象类,

publicabstractclassMyBaseAdapter<T>extendsBaseAdapter{

这是我们的getView

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
ViewHolderholder=ViewHolder.bind(position,convertView,parent,mLayRes,parent.getContext());
bindView(holder,list.get(position));
returnholder.getItemView();
}

现在我们的适配器已经完成百分之九十了,还差一点,我们需要写几个辅助方法,为了方便我们等会进行适配。

1.获取指定控件

public<TextendsView>TgetView(intid){
Tt=(T)mViews.get(id);
if(t==null){
t=itemView.findViewById(id);
mViews.put(id,t);
}
returnt;
}

在Viewholder中写一个getView方法,通过控件id来获取指定控件。

2.TextView控件输入数据

publicViewHoldersetText(intid,CharSequencetext){
Viewview=getView(id);
if(viewinstanceofView){
((TextView)view).setText(text);
}
returnthis;
}

3.ImageView输入图片

publicViewHoldersetImg(intid,intresId){
Viewview=getView(id);
if(viewinstanceofView){
((ImageView)view).setImageResource(resId);
}else
view.setBackgroundResource(resId);
returnthis;
}

4.复选框输入选定状态

publicViewHoldersetCheckable(intid,booleancheckable){
Viewview=getView(id);
if(viewinstanceofView){
((CheckBox)view).setChecked(checkable);
}
returnthis;
}

好啦,先在我们的适配器完全写完了,我们来看一下效果吧。

privatevoidinitTools(){
ListViewmLv=(ListView)findViewById(R.id.mlv);
adapter=newMyBaseAdapter<Student>(list,R.layout.item_one){
@Override
publicvoidbindView(ViewHolderholder,Studentobj){
holder.setText(R.id.name,obj.getName())
.setText(R.id.age,obj.getAge()+"")
.setText(R.id.sex,obj.getSex())
.setImg(R.id.head,obj.getImgId())
.setCheckable(R.id.mc,obj.isOver());
}
};
mLv.setAdapter(adapter);
}

关于ListView中怎么使用泛型适配器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

发布于 2021-06-13 23:19:02
收藏
分享
海报
0 条评论
183
上一篇:android中怎么解决中文字体向上偏移 下一篇:怎么使用Python3.8
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码