我正在尝试在我的 Fragment
中设置一个 ListView
。我正在从 Firebase 获取数据,并将其设置为我的 ListView
。在我的 Firebase 数据库中,我有一个父节点 patients
,它有 patient1
、patient2
等子节点以及我的 ListView 中的每个项目
代表一个病人。我的 ListView
将始终最多包含 2 个项目,因为我将列表设置为来自 Firebase 数据库的前两名患者。每当添加或删除新患者时,我都希望我的 listView
能够更新新患者数据。但是当添加新患者时,我的应用程序崩溃了。
Logcat 异常:-
01-10 14:20:20.966 17863-17863/com.abc.tempapp/AndroidRuntime: FATAL EXCEPTION: main
01-10 14:20:20.966 17863-17863/com.abc.tempapp E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
代码:-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
...
setListView();
...
}
public void setListView()
{
Firebase.setAndroidContext(context);
firebaseData = new Firebase("https://xyz.firebaseio.com");
firebaseData.child("patients").orderByChild("appointment-id").limitToFirst(2).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
patientList.clear();
for (DataSnapshot tempSnapshot : dataSnapshot.getChildren()) {
int tempId = Integer.parseInt(tempSnapshot.child("appointment-id").getValue().toString());
String tempContact = tempSnapshot.child("number").getValue().toString();
String tempName = tempSnapshot.child("name").getValue().toString();
long tempTime = Long.parseLong(tempSnapshot.child("arrival-time").getValue().toString());
Patient patient = new Patient(tempId, tempContact, tempName, epochToDate(tempTime));
patientList.add(patient);
}
if (myAdapter == null) {
myAdapter = new MyAdapter(context, patientList);
listView.setAdapter(myAdapter);
firebaseData.child("patients").addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
dataChanged();
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
dataChanged();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
@Override
public void onCancelled(FirebaseError firebaseError) {}
});
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {}
});
}
synchronized public void dataChanged()
{
Firebase.setAndroidContext(context);
firebaseData = new Firebase("https://xyz.firebaseio.com");
firebaseData.child("patients").orderByChild("appointment-id").limitToFirst(2).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
patientList.clear();
for (DataSnapshot tempSnapshot : dataSnapshot.getChildren()) {
int tempId = Integer.parseInt(tempSnapshot.child("appointment-id").getValue().toString());
String tempContact = tempSnapshot.child("number").getValue().toString();
String tempName = tempSnapshot.child("name").getValue().toString();
long tempTime = Long.parseLong(tempSnapshot.child("arrival-time").getValue().toString());
Patient patient = new Patient(tempId, tempContact, tempName, epochToDate(tempTime));
patientList.add(patient);
}
myAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(FirebaseError firebaseError) {}
});
}
我不知道我在这里错过了什么。这可能是一个非常基本的事情,我错了,希望有人纠正我。
最佳答案
错误消息说:“java.lang.NullPointerException:尝试在空对象引用上调用虚方法‘java.lang.String java.lang.Object.toString()’”
您在从 Firebase 提取数据的代码中调用了 toString()
:
int tempId = Integer.parseInt(tempSnapshot.child("appointment-id").getValue().toString());
String tempContact = tempSnapshot.child("number").getValue().toString();
String tempName = tempSnapshot.child("name").getValue().toString();
long tempTime = Long.parseLong(tempSnapshot.child("arrival-time").getValue().toString());
您收到的其中一个值显然是 null
,因此 toString()
失败。这可能是由于缺少值或您对结果形状的错误假设引起的 - 尝试记录 tempSnapshot
的内容或在那里设置断点并从调试器查看对象。
如果空值是由通常存在但有时丢失的数据引起的,您可以从原始类型切换到引用类型,即使用 Integer 代替 int 和 Long 代替 long。然后您可以在这些字段中存储空值,但您必须处理它们在程序的其余部分中为空值的可能性。
另一种可能性是,如果传入值为空,则使用一些默认值。
此外,如 Firebase documentation 中所述, getValue()
返回一个已解析的对象,例如Long 如果数据是整数,那么我们可以使用它来避免解析速度有点慢,只需将 Long 转换为 Integer。
例子:
Object tempIdObj = tempSnapshot.child("appointment-id").getValue();
Integer tempId = tempIdObj instanceof Long ? ((Long) tempIdObj).intValue() : null;
如果 appointment-id
包含非整数值,例如 xyz
或 234.0
,此代码还将设置 tempId 为 null。
关于android - notifyDataSetChanged() 在更改从 firebase 检索的 ListView 数据时导致 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34703775/