ListView通过Intent传递数据遇空指针与参数异常问题
解决ListView数据传递到Activity的空指针与查询异常问题
我来帮你一步步拆解并修复遇到的这些问题:
1. 先搞定 IllegalArgumentException: n <= 0: 0 错误
这个错误是因为从Firestore查询回来的placesList是空的(placeCount = 0),你直接调用randomGenerator.nextInt(placeCount)就触发了异常。我们需要先判断查询结果是否为空,再执行后续逻辑:
修改主Activity中onComplete里的代码:
if (task.isSuccessful()) { List<Places> placesList = new ArrayList<>(); for (DocumentSnapshot document : task.getResult()) { Places place = document.toObject(Places.class); placesList.add(place); } // 新增:先判断查询结果是否为空 if (placesList.isEmpty()) { Toast.makeText(ListViewPlaces.this, "没有找到符合条件的地点", Toast.LENGTH_SHORT).show(); return; } int placeCount = placesList.size(); Random randomGenerator = new Random(); // 注意:不要重新定义局部变量randomPlaceList,直接用类的成员变量 randomPlaceList.clear(); for (int i = 1; i <= 3; i++) { randomPlaceList.add(placesList.get(randomGenerator.nextInt(placeCount))); } // 同样不要重新定义mListView,用成员变量即可 mAdapter = new PlaceAdapter(randomPlaceList, ListViewPlaces.this); mListView.setAdapter(mAdapter); }
2. 修复 NullPointerException: ArrayList.get(int) 错误
这个坑有两个原因:
- 你在
onComplete里重新定义了局部变量randomPlaceList,覆盖了类的成员变量,导致后续点击时拿不到数据 - Firestore查询是异步的——你在
onCreate里直接设置了点击事件,但此时mAdapter可能还没初始化(查询还没完成)
修复步骤:
- 删掉
onComplete里的ArrayList<Places> randomPlaceList = new ArrayList<>();,直接使用类成员变量randomPlaceList - 把点击事件移到
onComplete内部(确保适配器已经初始化完成),同时增加空值判断:
修改后的点击事件代码:
// 把点击事件移到onComplete里,确保mAdapter已经初始化 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 双重保险:先判断适配器和选中项是否不为空 if (mAdapter == null) return; Places places = mAdapter.getItem(position); if (places == null) return; Intent intent = new Intent(ListViewPlaces.this, Card_activity.class); intent.putExtra("name", places.getName()); startActivity(intent); } });
另外,你的PlaceAdapter里有个小拼写错误:converView应该是convertView,建议修正避免后续混淆。
3. 修复第二个Activity的空指针问题
你的Card_activity里有两个明显错误:
getStringExtras是复数,返回的是Bundle对象,应该用getStringExtra("name")(单数)来获取单个字符串- 代码末尾少了分号,且没有判断
name是否为null,会触发空指针
修改后的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); // 修正:用getStringExtra,并增加空值判断 String name = getIntent().getStringExtra("name"); if (name != null) { mTextView.setText(name); } else { mTextView.setText("暂无名称"); } } // 别忘了实现onClick方法,否则会编译报错 @Override public void onClick(View v) { // 根据你的需求添加点击逻辑 } }
额外优化建议
- 不要用
getBaseContext()或getApplicationContext()初始化适配器,直接用当前Activity上下文(比如ListViewPlaces.this),避免上下文泄漏 - 你的
PlaceAdapter不需要自己保存dataSet,ArrayAdapter已经维护了数据源,直接用getItem(position)就能拿到数据,减少冗余 - 给Firestore查询添加失败回调,方便排查问题:
query.get().addOnCompleteListener(...) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.e("Firestore", "查询失败", e); Toast.makeText(ListViewPlaces.this, "查询失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } });
内容的提问来源于stack exchange,提问作者Spike Johnson
相关产品推荐
相关产品推荐

