Android 从Firebase中删除数据时应用程序崩溃
我正在为我的应用程序开发事件功能,我已经被这个bug困扰了两天 总之,我登录到应用程序并从Firebase中检索一个eventid,我将其设置为静态User.eventid。当应用程序切换到MainActivity时,静态User.eventid用于决定使用哪个片段:ViewEventsFragment或DefaultEventFragment(带2个按钮的空片段)如果User.eventid=“null”,则转到默认事件片段,否则转到查看事件片段 最初,用户处于事件中,因此user.eventid=“LyfLmM…”因此主活动将用户带到ViewEventsFragment。现在,在ViewEventsFragment中,我可以选择删除事件。执行此操作后,我将更新firebase eventid=“null”以供将来登录并更新要在MainActivity中使用的静态用户。eventid=“null”。然后启动意图并将用户带到MainActivity,应用程序将根据user.eventid决定切换到哪个片段。因为我刚刚更改了静态用户.eventid=“null”,所以应该将我带到DefaultEventsActivity 但这不起作用,我的应用程序反而崩溃了。我包括了从头到尾的代码和错误日志 LoginActivity.classAndroid 从Firebase中删除数据时应用程序崩溃,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,我正在为我的应用程序开发事件功能,我已经被这个bug困扰了两天 总之,我登录到应用程序并从Firebase中检索一个eventid,我将其设置为静态User.eventid。当应用程序切换到MainActivity时,静态User.eventid用于决定使用哪个片段:ViewEventsFragment或DefaultEventFragment(带2个按钮的空片段)如果User.eventid=“null”,则转到默认事件片段,否则转到查看事件片段 最初,用户处于事件中,因此user.event
// Retrieve information about the user from Firebase. One important field is eventid which represents
// the event that the user is part of. If eventid=="null", then the user is not in any event.
JSONObject obj = new JSONObject(s);
eventid = obj.getJSONObject(id).getString("eventid");
User.eventid = eventid;
...
startActivity(new Intent(SignIn.this, MainActivity.class));
// Once the user is taken to MainActivity, there is a bottom navigation that loads a fragment
// depending on the User.eventid retrieved in Login. If the user is an event, take them to
// ViewEventsFragment. if user is NOT in event, take them to DefaultEventsFragment
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment fragment;
switch (item.getItemId()) {
case R.id.event_button:
Log.i("ViewEventsFragment", "MainActivity: "+User.eventid);
if(User.eventid.equals("null")) {
fragment = fragmentA;
}
else {
fragment = fragmentB;
}
break;
...
fragmentManager.beginTransaction().replace(R.id.frame_layout, fragment).commit();
return true;
}
});
主课
// Retrieve information about the user from Firebase. One important field is eventid which represents
// the event that the user is part of. If eventid=="null", then the user is not in any event.
JSONObject obj = new JSONObject(s);
eventid = obj.getJSONObject(id).getString("eventid");
User.eventid = eventid;
...
startActivity(new Intent(SignIn.this, MainActivity.class));
// Once the user is taken to MainActivity, there is a bottom navigation that loads a fragment
// depending on the User.eventid retrieved in Login. If the user is an event, take them to
// ViewEventsFragment. if user is NOT in event, take them to DefaultEventsFragment
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment fragment;
switch (item.getItemId()) {
case R.id.event_button:
Log.i("ViewEventsFragment", "MainActivity: "+User.eventid);
if(User.eventid.equals("null")) {
fragment = fragmentA;
}
else {
fragment = fragmentB;
}
break;
...
fragmentManager.beginTransaction().replace(R.id.frame_layout, fragment).commit();
return true;
}
});
假设用户是事件的一部分。然后我们加载:
ViewEventsFragment.java
// In this fragment, the user is part of an event. This means that User.eventid is NOT "null" and
// user was redirected here from MainActivity. So first pull all the
// data from firebase to populate the fields
Firebase.setAndroidContext(getActivity());
pullFirebaseData();
// Pull data from firebase and populate fields
// This function should only be called if eventid is NOT null
// But for some reason, it's being called while it's null and gets an error
public void pullFirebaseData(){
eventid = User.eventid;
if((eventid==null) || (eventid.equals("null"))){
User.eventid = "null";
startActivity(new Intent(getActivity(), MainActivity.class));
}
Firebase reference = new Firebase("https://...firebaseio.com/events");
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
**Line144** name = dataSnapshot.child(eventid).child("eventName").getValue().toString();
date = dataSnapshot.child(eventid).child("eventDate").getValue().toString();
time = dataSnapshot.child(eventid).child("eventTime").getValue().toString();
...
}
// Suppose now user wants to delete the event.
leaveGroupButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// (1) First update Firebase by changing each users eventid to "null". This works.
// (2) Now, change User.eventid="null" since user is leaving the event and switch to
// MainActivity. Since the User.eventid="null", the user SHOULd be taken to
// DefaultEventsFragment and NOT back here.
// (3) Finally, delete the event from Firebase
(1) changeAllUserFirebase();
(2) User.eventid = "null"
startActivity(new Intent(getActivity(), MainActivity.class));
(3) deleteEvent();
}
}
});
// Remove the entire event from Firebase
public void deleteEvent(){
Firebase reference = new Firebase("https://grouptracker-ef84c.firebaseio.com/events");
reference.child(User.eventid).removeValue();
}
现在问题开始了。从日志中可以看出,我正在MainActivity中成功地获取eventid并切换到ViewEventFragment。现在,当我尝试删除它时,它会将我带回到ViewEventsFragments,而实际上它会将我带到MainActivity
2020-01-15 17:40:15.514 18350-18350/com.package.appname I/ViewEventsFragment: MainActivity: -LyfLmMmO1mkB0gvB9P7
2020-01-15 16:38:24.905 17166-17166/com.package.appname E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.package.appname, PID: 17166
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
at com.package.appname.Fragments.ViewEventsFragment$4.onDataChange(ViewEventsFragment.java:144)
at com.firebase.client.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:56)
at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:38)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
因此,我通过删除deleteEvent()对其进行了测试,结果非常理想。我切换到MainACtivity==>DefaultEventFragment。现在我不明白为什么从firebase中删除事件会使我的应用程序崩溃
尝试:因此我尝试将deleteEvent()函数移到Main。因此,一旦用户离开事件,它就会从ViewEventsFragment转到Main。然后,它主要应该删除事件。然而,该应用程序只是返回到ViewEventsFragment并崩溃。不确定是什么原因导致它强制转到ViewEventsFragment。“当您使用reference.addValueEventListener注册侦听器时,它将在每次侦听的数据更改时调用onDataChange,包括删除该数据时,这意味着将使用null调用它。您应该处理数据丢失的可能性,或者在使用removeEventListener删除数据并传入ValueEventListener的同一实例之前注销侦听器。”
-来自Reddit的汉堡包
由于我正在删除数据,我的侦听器总是在读取新的更改,并且随着数据的消失,它正在获取一些不存在的内容。基于上述逻辑,我重新构造了代码并创建了一个新的侦听器:
final Firebase reference = new Firebase("https://....firebaseio.com/...");
final ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
name = dataSnapshot.child(eventid).child("eventName").getValue().toString();
...
nameTextView.setText(name);
...
}
};
// Here, I'm registering the listener
reference.addValueEventListener(eventListener);
}
// *IMPORTANT*
leaveGroupButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
...
// I'm done with the listener so now I'm removing it
reference.removeEventListener(eventListener);
}
}
这一行的位置是
ViewEventsFragment.java:144
?错误在这一行,带有toString()
请指明发生错误的确切代码行。我用这些行进行了更新。代码甚至不应该转到这一行,因为我正在删除事件并调用意图切换到另一个活动。但由于某些原因,它没有转到MainActivity,而是重新加载活动并导致错误。错误是意料之中的因为它试图从不存在的东西中检索字符串。