Jorge Garnica
Jorge Garnica

Reputation: 1276

Firebase addValueEventListener keeps listening in other activity

I have this code in an Activity called "PrincipalActivity.java"

btnSignIn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        final String placa = edtPlaca.getText().toString().trim();
        final String token = edtToken.getText().toString().trim();
        if (TextUtils.isEmpty(placa)) {
            Toast.makeText(getApplicationContext(), "Ingrese una Placa", Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(token)) {
            Toast.makeText(getApplicationContext(), "Ingrese el Token de Seguridad", Toast.LENGTH_SHORT).show();
            return;
        }
        mapaIntent = new Intent(getApplicationContext(),MapaActivity.class);
        startActivity(mapaIntent);
        Toast.makeText(getApplicationContext(), "Principal", Toast.LENGTH_SHORT).show();
        myRef.child("lineas").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                try{
                    Object valor = "";
                    String clave = "";
                    mapaIntent = new Intent(getBaseContext(),MapaActivity.class);
                    for (DataSnapshot lineas: dataSnapshot.getChildren()) {//navegar por lineas
                        for (DataSnapshot placas: lineas.getChildren()){//navegar por placas
                            if (placas.getKey().toString().equals(placa.trim())) {
                                for (DataSnapshot llave : placas.getChildren()) {//navegar por campos de cada placa
                                    valor = llave.getValue();
                                    clave = llave.getKey();
                                    if (clave.equals("token")) {
                                        if (valor.equals(token.trim())) {
                                            Toast.makeText(getApplicationContext(), "Placa y Token correctos!!!", Toast.LENGTH_SHORT).show();
                                            startActivityForResult(mapaIntent,123);
                                        } else {
                                            Toast.makeText(getApplicationContext(), "Token de Seguridad incorrecto", Toast.LENGTH_SHORT).show();
                                        }
                                    }
                                }
                            }
                        }
                        Toast.makeText(getApplicationContext(),"La placa no existe",Toast.LENGTH_SHORT).show();

                    }
                }catch (Exception ex){
                    Toast.makeText(getApplicationContext(),"error leyendo",Toast.LENGTH_SHORT).show();
                }
            }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

Well, as you can see the code is part of listener of button called btnSigIn. Just see the try bloc, I'm trying to start other activity called MapaActivity. Also this intent is inside addValueEventListener (a firebase listener when a field change).

In my MapaActivity Class I have basically this

 class MyLocationListener implements LocationListener {

    MyLocationListener(){
        ubicacion = new Location("Inicio");
        ubicacion.setLatitude(0.0);
        ubicacion.setLongitude(0.0);
    }

    @Override
    public void onLocationChanged(Location location) {
        if (muestreando){
            ubicacion = location;
            txtLat.setText("Latitud: "+ location.getLatitude());
            txtLon.setText("Longitud: "+ location.getLongitude());
            myRef.child("lineas").child("1").child("ABC-123").child("latitud").setValue(location.getLatitude());
            myRef.child("lineas").child("1").child("ABC-123").child("longitd").setValue(location.getLongitude());
            setResult(1);
        }
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

As you can see is a listener that modify some parameters from the user location in Firebase.

THE PROBLEM

The first class works perfectly and sends me to the second activity (MapaActivity).

But, when the second activity modifies the firebase database for any reason (tha i can't undestand), the first activity also listen the change n firebase and it creates again de second activity and how that. It happens as many times as the location change (it refresh the firebase and the first activity listen and trhougt again the seond activity).

Anybody knows Why ? And how can i solve. Thank You.

Upvotes: 0

Views: 3274

Answers (5)

Mihir Patel
Mihir Patel

Reputation: 486

addListenerForSingleValueEvent will be called again if the activity is restarting, i.e. let's say you're launching some activity for result, when coming back to your activity, the listener will be called again. You need to deal with your listener onActivityResult to make sure it does not get attached to your database reference.

Upvotes: 2

Cătălin Florescu
Cătălin Florescu

Reputation: 5158

Unsubscribe events in onPause in your Activity.

@Override
public void onPause() {
    super.onPause();
    myRef.removeEventListener(yourValueEventListener);
}

Same for ChildEventListener.

Upvotes: 1

Saurabh Padwekar
Saurabh Padwekar

Reputation: 4074

From Google Firebase Reference

Read data once

You can use the addListenerForSingleValueEvent() method to simplify this scenario: it triggers once and then does not trigger again.

https://firebase.google.com/docs/database/android/read-and-write#read_data_once

Upvotes: 0

santosh kumar
santosh kumar

Reputation: 2962

addValueEventListener is not the event which can be triggered with click of a button or something. It will always be listening to Firebase changes and updates.

addValueEventListener it is a callback interface which is set when there is any change in Firebase database.

Once you jump to another activity stop listening to EventListener

you have method removeEventListener which can be used to remove lsiteners to avoid getting callback from firebase.

dbref.removeEventListener(yourListener);

Upvotes: 2

Yunus Kulyyev
Yunus Kulyyev

Reputation: 1022

Your ValueEventListener listen to any changes that occur in the firebase. Thus, you can use ChildEventListener instead of ValueEventListener:

mDatabaseReference.child("User").addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

With ChildEventListener, you can be more specific on when your code is supposed to read the database.

Upvotes: 0

Related Questions