首屏Fragment中Retrofit加载RecyclerView报数组越界问题求助
问题排查与解决方案
问题根源
- 初始化
UsersAdapter时硬编码传入size=4,且getItemCount()直接返回该固定值,完全忽略了usersModel集合的实际状态。 - 首屏加载时网络请求尚未完成,
usersModel是空集合,RecyclerView会根据getItemCount()返回的4条数据尝试绑定,调用usersModel.get(position)时触发数组越界异常。 - 切换Fragment后再切回时,网络请求已完成,
usersModel已有数据,因此不会触发异常。
修复方案
1. 修复Adapter核心逻辑
删除硬编码的size参数,根据usersModel的实际大小返回item数量,同时处理集合为null的情况:
public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UsersHolder> { Context mContext; List<UsersModel> usersModel; // 移除size参数,初始化时处理空集合 public UsersAdapter(Context mContext, List<UsersModel> usersModel) { this.mContext = mContext; this.usersModel = usersModel != null ? usersModel : new ArrayList<>(); } public void setUsersList(List<UsersModel> usersModel) { // 更新数据时同样处理null情况 this.usersModel = usersModel != null ? usersModel : new ArrayList<>(); notifyDataSetChanged(); } @NonNull @Override public UsersAdapter.UsersHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_users, parent, false); return new UsersHolder(view); } @Override public void onBindViewHolder(@NonNull UsersAdapter.UsersHolder holder, int position) { UsersModel model = usersModel.get(position); holder.name.setText(model.getName()); holder.description.setText(model.getDescription()); Glide.with(holder.itemView.getContext().getApplicationContext()) .load(model.getLogo()) .into(holder.logo); } @Override public int getItemCount() { // 返回集合实际大小,而非固定值 return usersModel.size(); } public static class UsersHolder extends RecyclerView.ViewHolder { private final ImageView logo; private final TextView name, description; public UsersHolder(@NonNull View itemView) { super(itemView); logo = itemView.findViewById(R.id.logo); name = itemView.findViewById(R.id.title); description = itemView.findViewById(R.id.description); } } }
2. 优化Fragment初始化与网络请求逻辑
- 初始化
usersList为非空的空集合,避免传递null给Adapter - 处理网络返回数据为null的情况
// 初始化空集合,避免传递null List<UsersModel> usersList = new ArrayList<>(); binding.recyclerViewUser.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); binding.recyclerViewUser.setOverScrollMode(View.OVER_SCROLL_NEVER); // 不再传入size参数 usersAdapter = new UsersAdapter(mContext, usersList); binding.recyclerViewUser.setAdapter(usersAdapter); Call<List<UsersModel>> getUersData = RetrofitClient.getInstance().getApi().getUsersData(); getUersData.enqueue(new Callback<>() { @Override public void onResponse(@NonNull Call<List<UsersModel>> call, @NonNull Response<List<UsersModel>> response) { if (response.isSuccessful() && response.body() != null) { usersList = response.body(); usersAdapter.setUsersList(usersList); Log.d("Retrofit success", "Yeah!"); long requestTime = response.raw().sentRequestAtMillis(); long responseTime = response.raw().receivedResponseAtMillis(); long apiTime = responseTime - requestTime; Log.d("Retrofit time", apiTime + "ms"); } else { Log.d("Retrofit info", "No data returned"); usersAdapter.setUsersList(null); } } @Override public void onFailure(@NonNull Call<List<UsersModel>> call, @NonNull Throwable t) { Log.d("Retrofit error", t.getMessage()); usersAdapter.setUsersList(null); } });
3. 可选:添加空状态提示
如果需要在无数据时给用户明确提示,可以在Fragment布局中添加空状态View,根据数据情况显示/隐藏:
// 在更新Adapter数据后执行 if (usersList == null || usersList.isEmpty()) { binding.emptyView.setVisibility(View.VISIBLE); binding.recyclerViewUser.setVisibility(View.GONE); } else { binding.emptyView.setVisibility(View.GONE); binding.recyclerViewUser.setVisibility(View.VISIBLE); }
内容的提问来源于stack exchange,提问作者zigg-zigg
相关产品推荐
相关产品推荐

