srijanshukla srijanshukla - 5 months ago 46
Android Question

Removing event listener as activity pauses or stops

I am facing a problem in removing an Event Listener.
I am using initialising a listener inside the onStart() in an Activity
after collecting the user data, the app shows a toast to the user that the data has been uploaded and then I call the onBackPressed() method.

But I notice that the listener is still running after the activity is Paused or Stopped, because it is creating toast called under onCancelled() event.

So I tried overriding the onPause and onStop methods.

@Override
public void onPause() {
super.onPause();
// Remove post value event listener
if (mListener != null) {
mReadReference.removeEventListener(mListener);
}
}


But this is causing an error :

java.lang.RuntimeException: Unable to pause activity {deventree.com.thetimothyinitiative/deventree.com.thetimothyinitiative.Attendance}: java.lang.NullPointerException: listener must not be null


I want to remove the ValueEventListener after the data is uploaded and before the activity calls the onBackPressed() method

Code for Activity:

public class Attendance extends Activity {

Map<String, Boolean> td;
ArrayList<String> valu;


private SparseBooleanArray sbArray;

private static final String TAG = "Attendance";

CustomAdapter myAdapter;
ListView listview;

private DatabaseReference mReadReference;
private DatabaseReference mPostReference;
private ValueEventListener mListener;

private Button mButton;
private Button btnAll;
private Button btnNone;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attendance);

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String eid=user.getEmail();
System.out.println(eid);
//String[] parts = eid.split("@");
String[] parts = eid.split("\\.");
eid = parts[0];
System.out.println(eid);
Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat("E dd-MM-yyyy 'at' HH:mm:ss");

final ListView listview = (ListView) findViewById(R.id.listq);
// Initialize Database
mReadReference = FirebaseDatabase.getInstance().getReference()
.child("Lists").child(eid);
mPostReference = FirebaseDatabase.getInstance().getReference()
.child("Users").child(eid).child(ft.format(dNow)).child("Attendance Record");

//UI Elements
btnAll=(Button)findViewById(R.id.button40);
btnNone=(Button)findViewById(R.id.button33);
mButton=(Button)findViewById(R.id.button42);

btnAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
for (int i = 0; i < listview.getCount(); i++) {
listview.setItemChecked(i, true);
}
}
});
btnNone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int len=listview.getCount();
int lou=listview.getChildCount();
System.out.println(len+" "+lou);
for ( int i=0; i < listview.getCount(); i++) {
listview.setItemChecked(i, false);
}
}
});

mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println("Hello MF");
SparseBooleanArray checked = listview.getCheckedItemPositions();
for (int i=0; i<checked.size(); i++) {
if (checked.valueAt(i)) {
String item = listview.getAdapter().getItem(checked.keyAt(i)).toString();
td.put(item, true);
}
else{
String item = listview.getAdapter().getItem(checked.keyAt(i)).toString();
td.put(item, false);
}
}
mPostReference.setValue(td);
for (Map.Entry entry : td.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}
Toast.makeText(getApplicationContext(), "Attendance Uploaded",Toast.LENGTH_SHORT).show();
onBackPressed();
}
});
}
@Override
public void onStart() {
super.onStart();
ValueEventListener mListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("here");
td = (Map<String,Boolean>) dataSnapshot.getValue();
for (Map.Entry<String, Boolean> entry : td.entrySet()) {
td.put(entry.getKey(),false);
}

valu = new ArrayList<String>(td.keySet());
ArrayAdapter<String> dataAdapter = new ArrayAdapter(getApplicationContext(), R.layout.rowview, valu);
listview = (ListView) findViewById(R.id.listq);
listview.setAdapter(dataAdapter);

}

@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
Toast.makeText(Attendance.this, "Failed to load list.",
Toast.LENGTH_SHORT).show();

}
};
mReadReference.addValueEventListener(mListener);
}

@Override
public void onStop() {
// Remove post value event listener
if (mListener != null) {
mReadReference.removeEventListener(mListener);
System.out.println("Doness");
}
super.onStop();

}

@Override
public void onPause() {

// Remove post value event listener
if (mListener != null) {
mReadReference.removeEventListener(mListener);
System.out.println("Here");
}
super.onPause();
}


}

Answer

Do it before super() calls. Like this :

@Override
public void onPause() {

    // Remove post value event listener
      if (mListener != null && mReadReference!=null) {
        mReadReference.removeEventListener(mListener);
       }
      super.onPause();
}  

Same for on Stop():

@Override
public void onStop() {

    // Remove post value event listener
    if (mListener != null && mReadReference!=null) {
        mReadReference.removeEventListener(mListener);
    }
    super.onStop();
}

EDIT 1 : Simply remove the declaration from onStart() Modify your onStart() like below code :

@Override
public void onStart() {
    super.onStart();

     // Removed  ValueEventListener mListener =new ValueEventListener() {

     mListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            System.out.println("here");
            td = (Map<String,Boolean>) dataSnapshot.getValue();
            for (Map.Entry<String, Boolean> entry : td.entrySet()) {
                td.put(entry.getKey(),false);
            }

            valu = new ArrayList<String>(td.keySet());
            ArrayAdapter<String> dataAdapter = new ArrayAdapter(getApplicationContext(), R.layout.rowview, valu);
            listview = (ListView) findViewById(R.id.listq);
            listview.setAdapter(dataAdapter);

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
            Toast.makeText(Attendance.this, "Failed to load list.",
                    Toast.LENGTH_SHORT).show();

        }
    };
    mReadReference.addValueEventListener(mListener);
}

Just declare it above onCreate() or above onStart().

Hope this helps :)

Comments