在ViewHolder中创建Spinner返回空值的问题排查
问题描述
我尝试在ViewHolder类中编写returnAsked方法返回Spinner,再在Activity中为这些Spinner设置适配器,以此解决在Activity外创建Spinner的问题,但这个方法返回的Spinner始终为空。
相关代码
ViewHolder中的方法
public @NonNull Spinner returnAsked(int i){ switch (i){ case 1: return avgDistance; case 2: return maxDistance; case 3: return gender; default: return gender; } }
Activity中的代码
GoogleSignUpViewHolder holder= new GoogleSignUpViewHolder(recyclerView); holder= new GoogleSignUpViewHolder(recyclerView); btnAdd= findViewById(R.id.BtnAdd); // Apply the adapter to the spinner adapterGender = ArrayAdapter.createFromResource(this, R.array.gender_array, android.R.layout.simple_spinner_item); adapterDistance = ArrayAdapter.createFromResource(this, R.array.avg_distance_array, android.R.layout.simple_spinner_item); // Specify the layout to use when the list of choices appears adapterGender.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapterDistance.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); if(holder.returnAsked(1)==null){ Toast.makeText(this, " CONTEXT", Toast.LENGTH_SHORT).show(); } holder.returnAsked(3).setAdapter(adapterGender); holder.returnAsked(1).setAdapter(adapterDistance); holder.returnAsked(2).setAdapter(adapterDistance);
RecyclerView适配器代码
public class GoogleSignUpAdapter extends RecyclerView.Adapter<GoogleSignUpViewHolder> { @NonNull @Override public GoogleSignUpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if(viewType == 0){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.birthdate_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 1){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gender_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 2){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.avg_distance_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 3){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.avg_speed_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 4){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.picture_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 5){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.address_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 6){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.city_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 7){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.country_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 8){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.height_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 9){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.id_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 10){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.max_distance_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 11){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.max_speed_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 12){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.phone_item,parent,false); return new GoogleSignUpViewHolder(view); } else if(viewType == 13){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.weight_item,parent,false); return new GoogleSignUpViewHolder(view); } return null; } @Override public void onBindViewHolder(@NonNull GoogleSignUpViewHolder holder, int position) { } @Override public int getItemViewType(int position) { return position; } @Override public int getItemCount() { return 14; } }
问题原因
- 错误实例化ViewHolder:你在Activity中直接
new GoogleSignUpViewHolder(recyclerView),但这个ViewHolder并没有加载对应的item布局,内部的Spinner控件完全没被初始化,自然返回null。RecyclerView的ViewHolder必须由Adapter的onCreateViewHolder方法创建,该方法会加载对应布局并完成控件初始化。 - ViewHolder控件范围问题:不同的ViewHolder对应不同的item布局,比如gender对应
gender_item布局,avgDistance对应avg_distance_item布局,每个ViewHolder只会初始化当前布局内的Spinner,其他Spinner成员变量默认都是null。
解决方案
把Spinner的初始化和适配器设置逻辑交给Adapter处理,不要在Activity中直接操作ViewHolder。
1. 修改ViewHolder,按需初始化控件
public class GoogleSignUpViewHolder extends RecyclerView.ViewHolder { public Spinner gender; public Spinner avgDistance; public Spinner maxDistance; public GoogleSignUpViewHolder(@NonNull View itemView) { super(itemView); // 根据布局类型初始化对应Spinner switch (itemView.getContext().getResources().getResourceName(itemView.getId())) { case "com.yourpackage:id/gender_item_root": // 替换为gender_item布局根视图的id gender = itemView.findViewById(R.id.spinner_gender); // 替换为布局内Spinner的id break; case "com.yourpackage:id/avg_distance_item_root": avgDistance = itemView.findViewById(R.id.spinner_avg_distance); break; case "com.yourpackage:id/max_distance_item_root": maxDistance = itemView.findViewById(R.id.spinner_max_distance); break; // 其他布局的控件初始化同理 } } }
2. 修改Adapter,在绑定阶段设置适配器
public class GoogleSignUpAdapter extends RecyclerView.Adapter<GoogleSignUpViewHolder> { private Context mContext; private ArrayAdapter<String> adapterGender; private ArrayAdapter<String> adapterDistance; public GoogleSignUpAdapter(Context context) { mContext = context; // 提前初始化适配器 adapterGender = ArrayAdapter.createFromResource(mContext, R.array.gender_array, android.R.layout.simple_spinner_item); adapterGender.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapterDistance = ArrayAdapter.createFromResource(mContext, R.array.avg_distance_array, android.R.layout.simple_spinner_item); adapterDistance.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); } @NonNull @Override public GoogleSignUpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = null; switch (viewType) { case 0: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.birthdate_item, parent, false); break; case 1: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gender_item, parent, false); break; case 2: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.avg_distance_item, parent, false); break; case 10: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.max_distance_item, parent, false); break; // 其他case保持原逻辑 } return new GoogleSignUpViewHolder(view); } @Override public void onBindViewHolder(@NonNull GoogleSignUpViewHolder holder, int position) { // 根据位置设置对应Spinner的适配器 switch (position) { case 1: if (holder.gender != null) { holder.gender.setAdapter(adapterGender); } break; case 2: if (holder.avgDistance != null) { holder.avgDistance.setAdapter(adapterDistance); } break; case 10: if (holder.maxDistance != null) { holder.maxDistance.setAdapter(adapterDistance); } break; } } @Override public int getItemViewType(int position) { return position; } @Override public int getItemCount() { return 14; } }
3. 简化Activity代码
// 初始化RecyclerView RecyclerView recyclerView = findViewById(R.id.your_recyclerview_id); recyclerView.setLayoutManager(new LinearLayoutManager(this)); GoogleSignUpAdapter adapter = new GoogleSignUpAdapter(this); recyclerView.setAdapter(adapter); btnAdd = findViewById(R.id.BtnAdd);
内容的提问来源于stack exchange,提问作者tavor doron
相关产品推荐
相关产品推荐

