自定义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 是采用了优化的方式;

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
BaseAdapter是Android开发中的一个抽象类,用于创建自定义适配器。适配器是连接数据和UI界面的桥梁,它负责将数据源中的数据逐个绑定到UI组件上,以展示给用户。BaseAdapter提供了一些方法,可以帮助我们实现自定义适配器。 以下是一个使用BaseAdapter创建自定义适配器的示例代码: ```java public class MyAdapter extends BaseAdapter { private Context mContext; private List<String> mData; public MyAdapter(Context context, List<String> data) { mContext = context; mData = data; } @Override public int getCount() { return mData.size(); } @Override public Object getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false); holder = new ViewHolder(); holder.textView = convertView.findViewById(R.id.text_view); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } String item = mData.get(position); holder.textView.setText(item); return convertView; } private static class ViewHolder { TextView textView; } } ``` 在这个示例中,我们创建了一个名为MyAdapter的自定义适配器,继承自BaseAdapter。在构造方法中,我们传入了上下文和数据源。然后,我们实现了BaseAdapter的四个方法:getCount()、getItem()、getItemId()和getView()。 - getCount()方法返回数据源的大小。 - getItem()方法返回指定位置的数据项。 - getItemId()方法返回指定位置的数据项的ID。 - getView()方法用于创建每个列表项的视图,并将数据绑定到视图上。 在getView()方法中,我们使用了ViewHolder模式来优化列表项的创建和复用。通过convertView参数判断是否需要创建新的视图,如果convertView为null,则创建新的视图,并将其缓存到ViewHolder中;如果convertView不为null,则直接从缓存中获取ViewHolder。然后,我们从数据源中获取对应位置的数据项,并将其绑定到视图上。 这样,我们就可以使用自定义的适配器MyAdapter来展示数据了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ang_qq_252390816

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值