从Firestore取数据填充ListView时出现非法参数异常求助
Firestore数据填充ListView时出现
java.lang.IllegalArgumentException: n <= 0: 0的解决方案 Hey, let's break down what's going wrong here and fix it step by step.
错误根源分析
The error java.lang.IllegalArgumentException: n <= 0: 0 is happening because you're calling randomGenerator.nextInt(randomPlaceList.size()) when randomPlaceList is empty (size = 0). The Random.nextInt(int n) method requires n to be greater than 0, so passing 0 triggers this exception.
Looking at your code, there are several critical issues in the loop where you're building the random place list, plus a few other minor bugs across your files:
- You're using the empty
randomPlaceListto generate random indexes instead of the populatedplacesList - There's a type mismatch: you're trying to assign an
int(random index) to aStringvariable, then add that String to aList<Places>(this should be a compile error, likely a typo when pasting code) - You're initializing the adapter and setting it on the ListView inside the loop, which is inefficient and unnecessary
- Your adapter class name doesn't match what you're using in the activity
- The
Placesentity is missing theimagefield and its getter/setter (required for your adapter's Glide call) - Syntax error and incorrect intent extra retrieval in
Card_activity
修正后的完整代码
1. ListViewPlaces 主活动
public class ListViewPlaces extends AppCompatActivity { FirebaseFirestore rootRef = FirebaseFirestore.getInstance(); CollectionReference placesRef = rootRef.collection("Places"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_view_places); placesRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { List<Places> placesList = new ArrayList<>(); for (DocumentSnapshot document : task.getResult()) { Places places = document.toObject(Places.class); placesList.add(places); } if (placesList.size() > 0) { int placeCount = placesList.size(); System.out.println(placesList.size()); Random randomGenerator = new Random(); List<Places> randomPlaceList = new ArrayList<>(); // 最多生成3个随机地点,如果总地点数不足3则取全部 int itemsToAdd = Math.min(3, placeCount); for (int i = 0; i < itemsToAdd; i++) { // 使用已填充的placesList的size生成有效索引 int randomIndex = randomGenerator.nextInt(placeCount); randomPlaceList.add(placesList.get(randomIndex)); } // 循环结束后一次性初始化适配器并设置到ListView ListView mListView = findViewById(R.id.place_list); PlaceAdapter placesAdapter = new PlaceAdapter((ArrayList<Places>) randomPlaceList, getApplicationContext()); mListView.setAdapter(placesAdapter); // 添加点击事件跳转到Card_activity mListView.setOnItemClickListener((parent, view, position, id) -> { Places selectedPlace = randomPlaceList.get(position); Intent intent = new Intent(ListViewPlaces.this, Card_activity.class); intent.putExtra("name", selectedPlace.getName()); startActivity(intent); }); } else { // 处理Firestore未加载到任何数据的情况 Toast.makeText(ListViewPlaces.this, "未找到任何地点数据", Toast.LENGTH_SHORT).show(); } } else { // 处理Firestore数据获取失败的情况 Toast.makeText(ListViewPlaces.this, "加载地点失败: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); } } }); } }
2. Places 实体类
public class Places { private String name; private String image; // 补充适配器需要的image字段 // Firestore要求的空构造函数 public Places() {} public Places(String name, String image) { this.name = name; this.image = image; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } }
3. PlaceAdapter 适配器
class PlaceAdapter extends ArrayAdapter<Places> { private ArrayList<Places> dataSet; Context mContext; private static class ViewHolder { TextView name_text; ImageView image_text; } public PlaceAdapter(ArrayList<Places> dataSet, Context context) { super(context, R.layout.item_list, dataSet); this.dataSet = dataSet; this.mContext = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { Places places = getItem(position); ViewHolder viewHolder; final View result; if (convertView == null) { viewHolder = new ViewHolder(); LayoutInflater inflater = LayoutInflater.from(getContext()); convertView = inflater.inflate(R.layout.item_list, parent, false); viewHolder.name_text = convertView.findViewById(R.id.text_image_id); viewHolder.image_text = convertView.findViewById(R.id.image_id); result = convertView; convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); result = convertView; } viewHolder.name_text.setText(places.getName()); Glide.with(getContext()).load(places.getImage()).into(viewHolder.image_text); return convertView; } }
4. Card_activity 跳转目标活动
public class Card_activity extends AppCompatActivity implements View.OnClickListener { TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.massive_places); mTextView = findViewById(R.id.head_name); // 修正语法错误和intent extra获取方式 String name = getIntent().getStringExtra("name"); mTextView.setText(name); } @Override public void onClick(View v) { // 这里可以实现你需要的点击逻辑 } }
关键修复总结
- 替换
randomGenerator.nextInt(randomPlaceList.size())为randomGenerator.nextInt(placeCount),使用已填充的placesList的大小生成有效索引 - 修复了向
randomPlaceList添加元素时的类型不匹配问题 - 将适配器初始化逻辑移到循环外部,避免重复创建和设置
- 补充了
Places实体类缺失的字段和方法,适配适配器的需求 - 修正了
Card_activity中的语法错误和intent数据获取方式 - 添加了Firestore数据加载失败和空数据的错误处理
内容的提问来源于stack exchange,提问作者Spike Johnson
相关产品推荐
相关产品推荐

