简体   繁体   中英

App crash after remove value of Firebase Database

I have a problem when I try removing values of firebase database, It's works correctly but my app still crashing:/

So I managed to get the code to work which adds a value to "Carte".

But now I'm trying with a NumberPicker to remove a certain number of Carte and add entries to something else.

Here is my code which adds entries with a loop.

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();


    }

It works without problems. but when I add the code to remove values from Carte contest_fragment code

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

And the logs indicate an error in another fragment:/

This is the entire logCat error:

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

Account Fragment code

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);

    }

}

}

**EDIT: **

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) {}
                        });

The application no longer crashes. But I need this code x)

Thank's in advance.

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.

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 .

This requite the following steps:

  1. Add a field in your fragment to track the listener:

     ValueEventListener mFirebaseListener
  2. 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);
  3. Remove the listener in onDestroyView or onStop :

     FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).removeEventListener(mFirebaseListener);

See:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM