Android - 在 firebase 数据库中杀死一个 child 会杀死我的应用程序

标签 android firebase firebase-realtime-database

在我的应用程序中,我使用此 ConnectionInformation.java 为每个用户存储数据列表。

package trickandroid.fulllogin;

/**
 * Created by Simon Peter on 19-May-17.
 */

public class ConnectionInformation {

    String due, selectArea, connectionNum, doorNum, conName, phoneNum, aadharNum, rationNum;

    public  ConnectionInformation(){

    }

    public ConnectionInformation(String due, String selectArea, String connectionNum, String doorNum, String conName, String phoneNum, String aadharNum, String rationNum) {
        this.connectionNum = connectionNum;
        this.doorNum = doorNum;
        this.conName = conName;
        this.phoneNum = phoneNum;
        this.aadharNum = aadharNum;
        this.rationNum = rationNum;
        this.selectArea = selectArea;
        this.due = due;
    }

    public String getDue() {
        return due;
    }

    public void setDue(String due) {
        this.due = due;
    }

    public String getSelectArea() {
        return selectArea;
    }

    public void setSelectArea(String selectArea) {
        this.selectArea = selectArea;
    }

    public String getConnectionNum() {
        return connectionNum;
    }

    public void setConnectionNum(String connectionNum) {
        this.connectionNum = connectionNum;
    }

    public String getDoorNum() {
        return doorNum;
    }

    public void setDoorNum(String doorNum) {
        this.doorNum = doorNum;
    }

    public String getConName() {
        return conName;
    }

    public void setConName(String conName) {
        this.conName = conName;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public String getAadharNum() {
        return aadharNum;
    }

    public void setAadharNum(String aadharNum) {
        this.aadharNum = aadharNum;
    }

    public String getRationNum() {
        return rationNum;
    }

    public void setRationNum(String rationNum) {
        this.rationNum = rationNum;
    }
}

将数据添加到 firebase 效果很好。这是我的数据库结构。 enter image description here

这是我的 showData() 方法,其中调用 .getDoorNum() 以将其显示在 ListView 上。

private void showData(DataSnapshot dataSnapshot) {
        if (expandableListView.getVisibility()==View.VISIBLE) {
            for (DataSnapshot ds : dataSnapshot.getChildren()) {
                ConnectionInformation cInfo = new ConnectionInformation();
                cInfo.setDoorNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getDoorNum());
                cInfo.setPhoneNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getPhoneNum());
                cInfo.setAadharNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getAadharNum());
                cInfo.setRationNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getRationNum());

                ArrayList<String> users = new ArrayList<>();
                users.add(cInfo.getDoorNum());
                users.add(cInfo.getPhoneNum());
                users.add(cInfo.getAadharNum());
                users.add(cInfo.getRationNum());

                ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, users);
                expandableListView.setAdapter(adapter);
            }
        }
    }

我使用此代码删除 child 。

disBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mdata.child(oldArea).child(key).removeValue();
                connection.child(oldArea).child(key).removeValue();
                toast("Connection Number " + oldNum + " Disconnected Successfully");
                startActivity(new Intent(DisconnectActivity.this,AreaGridActivity.class));
            }
        });

代码在数据库中运行良好,但我的应用程序因此错误而崩溃...

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String trickandroid.fulllogin.ConnectionInformation.getDoorNum()' on a null object reference
                                                                          at trickandroid.fulllogin.DetailsActivity.showData(DetailsActivity.java:449)
                                                                          at trickandroid.fulllogin.DetailsActivity.access$100(DetailsActivity.java:33)
                                                                          at trickandroid.fulllogin.DetailsActivity$3.onDataChange(DetailsActivity.java:129)
                                                                          at com.google.android.gms.internal.zzbpx.zza(Unknown Source)
                                                                          at com.google.android.gms.internal.zzbqx.zzZS(Unknown Source)
                                                                          at com.google.android.gms.internal.zzbra$1.run(Unknown Source)
                                                                          at android.os.Handler.handleCallback(Handler.java:751)
                                                                          at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                          at android.os.Looper.loop(Looper.java:154)
                                                                          at android.app.ActivityThread.main(ActivityThread.java:6236)
                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)

https://gist.github.com/SimonPeter1909/d70be328dd6d9b099a8a96454922432f DetailsActivity.java

我试了很多方法都无法通过错误...

最佳答案

这里的情况是您有一个 ValueEventListener,它在添加监听器时触发一次,然后在数据更改时再次触发。监听器明确期望找到具有特定 areaNamekey 的条目。

这在监听器第一次运行时很好,但是在单击按钮时,您会删除带有该 areaNamekey 的条目。这再次触发监听器(您更改了数据),监听器尝试对那个 areaNamekey 处的条目做一些事情,它不存在,你得到一个NullPointerException

有很多方法可以避免这种情况,但您可能需要重新考虑流程以及您想要发生的事情。

此处的快速解决方法是在尝试使用之前尝试检查该条目是否存在:

if(ds.child(userID).child("Connection Detail").child(areaName).child(key).exists()) {
    ConnectionInformation cInfo = new ConnectionInformation();
    cInfo.setDoorNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getDoorNum());
    cInfo.setPhoneNum(ds.child(userID).child("Connection Detail").child(areaName).child(key).getValue(ConnectionInformation.class).getPhoneNum());
...
...
} else {
//that entry doesn't exist, do something else
}

关于Android - 在 firebase 数据库中杀死一个 child 会杀死我的应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44288309/

相关文章:

android - 快速修复 NetworkOnMainThreadException

android - 在 Android 应用程序中正确加载资源(使用 openGL)

android - 简单的待办事项列表示例在 Android 上不起作用

node.js - Firebase 身份验证与云 sql 混合

ios - 检索新的 Firebase 数据 - iOS Swift

android - 如何在不验证(登录/注册)用户的情况下保护 Firebase 实时数据库?

swift - 注册过程中 Firebase 数据无效

Android - ArrayAdapter 不工作 - NullPointerException

ios - 从共享扩展上传到 firebase 存储

javascript - 如何构造 Firebase 实时数据库读取请求 : Order by Key's Child