自定义BaseAdapter如何重写getItem和getItemId
Posted Ang_qq_252390816
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义BaseAdapter如何重写getItem和getItemId相关的知识,希望对你有一定的参考价值。
前言
在自定义BaseAdapter的时候经常忽略getItem()和getItemId()两个方法,最近在使用Spinner实现下拉框的时候配和BaseAdapter实现自定义布局;但是按常规方法不重写getItem()和getItemId(),也就是默认的写法导致出现了一些问题;所以这里研究了一下BaseAdapter的源码;
方法解释
getItem() 获取与数据集中指定位置关联的数据项
getItemId() 获取与列表中指定位置关联的行ID
一般自定义BaseAdapter(对BaseAdapter做了优化的写法,自定义ViewHolder复用view)如下:
class MyBaseAdapter extends BaseAdapter {
private List list = new ArrayList<>();
public MyBaseAdapter(List list) {
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {//获取视图
LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = layoutInflater.inflate(R.layout.adapter_item, null);
view.setTag(holder);
holder.imageView = view.findViewById(R.id.imageView);
holder.textView = view.findViewById(R.id.textView);
}else {
holder = (ViewHolder) view.getTag(); //复用View
}
holder.imageView.setImageResource(list.get(i).getUrlInt());
holder.textView.setText(list.get(i).getName());
return view;
}
static class ViewHolder {
ImageView imageView;
TextView textView;
}
}
可以看到自定义BaseAdapter自动生成的getItem()和getItemId()一般不做改变,只重写getView和getCount这个两个方法;
如果和Spinner配合使用,Spinner设置setOnItemSelectedListener监听,在onItemSelected种通过getItemAtPosition(i) 和 getSelectedItem()方法获取点击的item的数据时,会引发空指针,就是因为没有重写getItem()方法;
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView adapterView, View view, int i, long l) {
TextView textView = view.findViewById(R.id.textView);
Toast.makeText(MainActivity.this, textView.getText(), Toast.LENGTH_SHORT).show();
adapterView.getItemAtPosition(i);//空指针
adapterView.getSelectedItem(); //空指针
}
@Override
public void onNothingSelected(AdapterView adapterView) {
}
});
查看AdapterView源码发现getItemAtPosition(i) 和 getSelectedItem()都调用了getAdapter()获取一个Adapter,从源码也可以看出getAdapter是一个抽象方法,需要子类重写,我们使用的Spinner就是AdapterView的子类从源码不难发现,使用Spinner的时候会设置一个Adapter;所以这个getAdapter获取到的Adapter就是我们给Spinner设置的自定义的BaseAdapter;显然getItemAtPosition() 和 getSelectedItem()中的 adapter.getItem(selection)最终调用的是自定义的BaseAdapter中的getItem()方法获取到的数据是点击某个Item的数据;所以出现空指针的问题所在就是没有重写BaseAdapter中的getItem()方法;
public Object getSelectedItem() {
T adapter = getAdapter();
int selection = getSelectedItemPosition();
if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
return adapter.getItem(selection);
} else {
return null;
}
}
public Object getItemAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? null : adapter.getItem(position);
}
public abstract T getAdapter();
接下怎么从写getItem和getItemId方法呢;我们可以查看一下ArrayAdapter的源码就知道怎么写了,
@Override
public @Nullable T getItem(int position) {
return mObjects.get(position); //mObjects就是上面我们自定义的MyBaseAdapter 中的list;
}
@Override
public long getItemId(int position) {
return position;
}
所以最终的自定义的BaseAdapter
class MyBaseAdapter extends BaseAdapter {
private List list = new ArrayList<>();
public MyBaseAdapter(List list) {
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = layoutInflater.inflate(R.layout.adapter_item, null);
view.setTag(holder);
holder.imageView = view.findViewById(R.id.imageView);
holder.textView = view.findViewById(R.id.textView);
}else {
holder = (ViewHolder) view.getTag(); //复用View
}
holder.imageView.setImageResource(list.get(i).getUrlInt());
holder.textView.setText(list.get(i).getName());
return view;
}
static class ViewHolder {
ImageView imageView;
TextView textView;
}
}
以上自定义BaseAdapter 是采用了优化的方式;
以上是关于自定义BaseAdapter如何重写getItem和getItemId的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据添加到 listView 的自定义 BaseAdapter - Android
如何在android中使用baseadapter刷新自定义列表视图