删除Firebase数据库的值后,应用程序崩溃 [英] App crash after remove value of Firebase Database
问题描述
当我尝试删除firebase数据库的值时遇到问题,它可以正常工作,但我的应用仍然崩溃:/
I have a problem when I try removing values of firebase database, It's works correctly but my app still crashing :/
所以我设法使代码起作用,该代码为"Carte"添加了一个值.
So I managed to get the code to work which adds a value to "Carte".
但是现在我正在尝试使用NumberPicker删除一定数量的Carte并将条目添加到其他条目中.
But now I'm trying with a NumberPicker to remove a certain number of Carte and add entries to something else.
这是我的代码,该代码添加带有循环的条目.
if (i == R.id.ParticipCarte1) {
FirebaseUser user = mAuth.getCurrentUser();
final NumberPicker np = new NumberPicker(getActivity());
np.setMinValue(1);
FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Integer nbrcarte = dataSnapshot.child("carte").getValue(Integer.class);
if (dataSnapshot.exists()) {
np.setMaxValue(nbrcarte);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
final AlertDialog.Builder builder1 = new AlertDialog.Builder(getContext());
builder1.setView(np);
builder1.setMessage(R.string.add_particip_msg);
builder1.setCancelable(true);
builder1.setPositiveButton(
R.string.confirme_particip,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final int nbrFois = np.getValue();
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
int a = 0;
while (a < nbrFois) {
writeNewUser1(user.getEmail());
a++;
}
}
});
builder1.setNegativeButton(
R.string.reset_pass_no_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
}
它可以正常工作.但是当我添加代码以从Carte race_fragment代码中删除值时
if (i == R.id.ParticipCarte1) {
FirebaseUser user = mAuth.getCurrentUser();
final NumberPicker np = new NumberPicker(getActivity());
np.setMinValue(1);
FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Integer nbrcarte = dataSnapshot.child("carte").getValue(Integer.class);
if (dataSnapshot.exists()) {
np.setMaxValue(nbrcarte);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
final AlertDialog.Builder builder1 = new AlertDialog.Builder(getContext());
builder1.setView(np);
builder1.setMessage(R.string.add_particip_msg);
builder1.setCancelable(true);
builder1.setPositiveButton(
R.string.confirme_particip,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final int nbrFois = np.getValue();
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
mDatabase.child("users").child(user.getUid()).child("carte").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Integer carte = mutableData.getValue(Integer.class);
mutableData.setValue(carte - nbrFois);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {}
});
int a = 0;
while (a < nbrFois) {
writeNewUser1(user.getEmail());
a++;
}
}
});
builder1.setNegativeButton(
R.string.reset_pass_no_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
}
它在数据库中工作正常,但是应用程序崩溃了
It works fine in the database but the application crashes
并且日志在另一个片段中指示错误:/
这是整个logCat错误:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.victorapp.winid, PID: 9923
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getString(int)' on a null object reference
at com.victorapp.winid.Account_fragment$1.onDataChange(Account_fragment.java:85)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.2.1:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.2.1:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.2.1:55)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7506)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.Zygote
帐户片段代码
public class Account_fragment extends Fragment implements View.OnClickListener {
FirebaseAuth auth;
FirebaseUser user;
TextView profileTxt;
DatabaseReference reference;
DatabaseReference DeleteRef;
Button NbrCarte;
private FirebaseAuth mAuth;
public Account_fragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_account_fragment, container, false);
auth = FirebaseAuth.getInstance();
profileTxt = rootView.findViewById(R.id.BonjourText);
user = auth.getCurrentUser();
NbrCarte = rootView.findViewById(R.id.btnCartes);
rootView.findViewById(R.id.BtnDisconnect).setOnClickListener(this);
rootView.findViewById(R.id.btnDelete).setOnClickListener(this);
rootView.findViewById(R.id.btnPass).setOnClickListener(this);
rootView.findViewById(R.id.btnCartes).setOnClickListener(this);
mAuth = FirebaseAuth.getInstance();
reference = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid());
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
String username = dataSnapshot.child("username").getValue().toString();
profileTxt.setText(getContext().getString(R.string.welcome_user) + username);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
String nbrcarte = dataSnapshot.child("carte").getValue().toString();
NbrCarte.setText(nbrcarte + getString(R.string.cartes_title));
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
return rootView;
}
private void signOut() {
mAuth.signOut();
Intent SignOutIntent = new Intent(getActivity(), MainActivity.class);
Account_fragment.this.startActivity(SignOutIntent);
}
private String email = "";
private void lostPassword (){
final EditText input = new EditText(getActivity());
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
final AlertDialog.Builder builderLost = new AlertDialog.Builder(getContext());
builderLost.setTitle(R.string.reset_password);
builderLost.setMessage(R.string.type_email);
builderLost.setView(input);
builderLost.setCancelable(true);
builderLost.setPositiveButton(
R.string.reset_pass_ok_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id){
email = input.getText().toString();
auth.sendPasswordResetEmail(email)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Email sent.");
Toast.makeText(getActivity(),
getActivity().getText(R.string.email_send) + email,
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(),
getActivity().getText(R.string.email_err) + email,
Toast.LENGTH_LONG).show();
}
}
});
}
});
builderLost.setNegativeButton(
R.string.reset_pass_no_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = builderLost.create();
alert11.show();
}
public void onClick(View v) {
int i = v.getId();
if (i == R.id.BtnDisconnect) {
signOut();
}
if (i == R.id.btnDelete){
final AlertDialog.Builder builderSuppr = new AlertDialog.Builder(getContext());
builderSuppr.setMessage(R.string.delete_alert_msg);
builderSuppr.setCancelable(true);
builderSuppr.setPositiveButton(
R.string.reset_pass_ok_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id){
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Compte supprimer.");
DeleteRef = FirebaseDatabase.getInstance().getReference()
.child("users").child(user.getUid());
DeleteRef.removeValue();
signOut();
}
}
});
}
});
builderSuppr.setNegativeButton(
R.string.reset_pass_no_btn,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = builderSuppr.create();
alert11.show();
}
if (i == R.id.btnPass){
lostPassword();
}
if (i == R.id.btnCartes){
Intent CartesIntent = new Intent(getActivity(), referralActivity.class);
Account_fragment.this.startActivity(CartesIntent);
}
}
}
****
但是我不明白的是,当我删除此代码时:
but what I can't understand is that when I remove this code:
mDatabase.child("users").child(user.getUid()).child("carte").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Integer carte = mutableData.getValue(Integer.class);
mutableData.setValue(carte - nbrFois);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {}
});
应用程序不再崩溃.但是我需要这个代码x)
The application no longer crashes. But I need this code x)
先谢谢了.
推荐答案
您要在片段的onCreateView
中附加一个永久侦听器.由于您从未删除过监听程序,因此只要您的应用程序运行,它就会一直观察数据库中的数据.因此,当片段不再(或尚未)附加到视图时,其onDataChange
可能会被调用.
You're attaching a permanent listener in the onCreateView
of your fragment. Since you never remove the listener, it keeps observing the data in the database as long as your app runs. Because of this, its onDataChange
may get called when the fragment is no longer (or not yet) attached to the view.
由于这个原因,当片段与活动分离时,您应该小心删除监听器.我建议在onStart()
中附加侦听器,然后在onStop
中将其删除,但是由于您在onCreateView
中附加了它,因此也可以在onDestroyView
中将其删除.
For this reason you should take care to remove the listener when the fragment is detached from the activity. I'd recommend attaching the listener in onStart()
and then removing it in onStop
, but since you attach it in onCreateView
you can also remove it in onDestroyView
.
这需要执行以下步骤:
-
在片段中添加一个字段以跟踪侦听器:
Add a field in your fragment to track the listener:
ValueEventListener mFirebaseListener
在附加onCreateView
或onStart
时将其设置为侦听器字段:
Set the listener field in the onCreateView
or onStart
when you attach it:
mFirebaseListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Integer nbrcarte = dataSnapshot.child("carte").getValue(Integer.class);
if (dataSnapshot.exists()) {
np.setMaxValue(nbrcarte);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).addValueEventListener(mFirebaseListener);
删除onDestroyView
或onStop
中的侦听器:
Remove the listener in onDestroyView
or onStop
:
FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).removeEventListener(mFirebaseListener);
请参阅:
- Why getContext() in fragment sometimes returns null?
- the Android documentation on the lifecycle of a fragment
这篇关于删除Firebase数据库的值后,应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!