更改从firebase检索的listview数据时,notifyDataSetChanged()会导致NullPointerException

时间:2016-01-10 09:08:50

标签: android android-listview firebase

我正在尝试在ListView内设置Fragment。我从Firebase获取数据,我将其设置为ListView。在我的Firebase数据库中,我有一个父节点patients,其中包含patient1patient2等子节点,我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) {}
        });

    }

我不知道我在这里缺少什么。我错了可能是一件非常基本的事情,希望有人纠正我。

1 个答案:

答案 0 :(得分:2)

错误消息说:“java.lang.NullPointerException:尝试在空对象引用上调用虚方法'java.lang.String java.lang.Object.toString()'”

您的代码中有toString()次调用,您从Firebase中提取数据:

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。然后你可以在这些字段中存储空值,但你必须处理它们在程序的其余部分中为空的可能性。

如果传入的值为null,则另一种可能性是使用一些默认值。

此外,如Firebase documentation中所述,getValue()会返回已解析的对象,例如如果数据是整数,那么我们可以使用它来避免解析有点慢,只需将Long转换为整数。

示例:

Object tempIdObj = tempSnapshot.child("appointment-id").getValue();
Integer tempId = tempIdObj instanceof Long ? ((Long) tempIdObj).intValue() : null;

如果appointment-id包含非整数值,例如xyz234.0,此代码也会将tempId设置为null。

相关问题