Android自定义Spinner加载数据源点击下拉崩溃问题求助
解决Spinner自定义布局后下拉崩溃的问题
嘿,我来帮你搞定这个Spinner点击下拉就崩溃的问题!咱们先拆解问题根源,再一步步解决。
问题原因分析
从你的崩溃日志和代码来看,核心问题出在Spinner的双视图机制和ArrayAdapter的使用方式上:
- Spinner有两个核心视图方法:
getView()负责显示当前选中的项,getDropDownView()负责显示下拉展开后的每一项 - 你在
HCPListAdapter的构造器里传入的第二个参数是0:super(context, 0, users); - 你只重写了
getView()来加载自定义布局,但getDropDownView()沿用了ArrayAdapter的默认实现——它会尝试用构造器里的0作为布局ID去加载视图,这显然找不到有效资源,所以抛出了Resources$NotFoundException(Resource ID #0x0找不到)
解决方案
这里有两种靠谱的解决方式,你可以根据需求选择:
方案一:重写getDropDownView()方法(推荐,更灵活)
这种方式适合后续可能需要区分「选中项布局」和「下拉项布局」的场景,直接在HCPListAdapter中添加getDropDownView()的实现,逻辑和getView()保持一致即可:
public class HCPListAdapter extends ArrayAdapter<User> { public HCPListAdapter(Context context, List<User> users){ super(context, 0, users); } @NonNull @Override public View getView(int position, View convertView, @NonNull ViewGroup parent) { // 原有getView逻辑不变 if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.hcp_dropdown, parent, false); } HCPViewHolder viewHolder = (HCPViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new HCPViewHolder(); viewHolder.name = convertView.findViewById(R.id.Row_assessment_file_for_list_assessment_text_name); convertView.setTag(viewHolder); } User user = getItem(position); if (user != null) { viewHolder.name.setText(user.getTitle() + ". " + user.getLastname() + ", " + user.getFirstname()); } else { viewHolder.name.setText(R.string.error_unknown); } return convertView; } // 新增getDropDownView方法 @NonNull @Override public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.hcp_dropdown, parent, false); } HCPViewHolder viewHolder = (HCPViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new HCPViewHolder(); viewHolder.name = convertView.findViewById(R.id.Row_assessment_file_for_list_assessment_text_name); convertView.setTag(viewHolder); } User user = getItem(position); if (user != null) { viewHolder.name.setText(user.getTitle() + ". " + user.getLastname() + ", " + user.getFirstname()); } else { viewHolder.name.setText(R.string.error_unknown); } return convertView; } private class HCPViewHolder{ public TextView name; } }
方案二:修改ArrayAdapter构造器参数(适合布局完全一致的场景)
如果你的选中项和下拉项布局完全相同,可直接修改构造器,将第二个参数从0改为自定义布局IDR.layout.hcp_dropdown,这样ArrayAdapter的默认实现会自动用该布局加载下拉视图:
public class HCPListAdapter extends ArrayAdapter<User> { // 修改构造器的第二个参数 public HCPListAdapter(Context context, List<User> users){ super(context, R.layout.hcp_dropdown, users); } @NonNull @Override public View getView(int position, View convertView, @NonNull ViewGroup parent) { // 原有getView逻辑不变 if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.hcp_dropdown, parent, false); } HCPViewHolder viewHolder = (HCPViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new HCPViewHolder(); viewHolder.name = convertView.findViewById(R.id.Row_assessment_file_for_list_assessment_text_name); convertView.setTag(viewHolder); } User user = getItem(position); if (user != null) { viewHolder.name.setText(user.getTitle() + ". " + user.getLastname() + ", " + user.getFirstname()); } else { viewHolder.name.setText(R.string.error_unknown); } return convertView; } private class HCPViewHolder{ public TextView name; } }
额外提示
如果后续你想让选中项显示简洁信息(比如仅姓名),下拉项展示邮箱等额外内容,只需在getView()和getDropDownView()中分别加载不同布局,或在同一布局里控制控件的显示隐藏即可。
内容的提问来源于stack exchange,提问作者Mwikala Kangwa
相关产品推荐
相关产品推荐

