Android - Firebase - Do I need to remove EVERY sin

2019-04-26 14:33发布

问题:

I did a reasonable amount of research and can not find the answer I need.

What I DO know: When I attach a ValueEventListener to a database reference, I know I need to remove it later (finding that out the hard way now with some massive memory leakage.

What I DON'T know: Do I also need to detach all other listeners? (This is to include Firebase Database, Storage, and Auth, the three APIs I am using)

Example:

UploadTask uploadTask = ref.putFile(uploadFile);

uploadTask.addOnFailureListener(new OnFailureListener() {
    //@Override code here
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TakeSnapshot>() {
    //@Override code here
}).addOnProgressListner(new OnProgressListner<UploadTask.TakeSnapshot>() {
    //@Override code here
};

I think that's enough to show you the point of what I mean. This is how my actual code is currently structured.

Questions:

  1. Do I need to remove all of those listeners just in case the activity is terminated (system decision, phone dies, whatever) before that callback happens?
  2. Can I bundle them up somehow and terminate them all three at once because I have like 30 of these in my code and really don't feel like restructuring all of it in order to assign all these listeners to variables JUST so I can pass them into the "removeBlahBlahBlahListener(listenerVariable)" over and over.
  3. Slightly off topic, but, I am too lazy to move all my code from onCreate to onStart... is is bad practice for me to remove all these listeners, finish things up, call finish() (or whatever it is that kills off an activity, although I guess this is not guaranteed) and just recreate the activity from scratch? It's a small simple app so the overhead of re-creating the activity is no biggie. Just curious what is "right".

I imagine this is just a result of poor planning and lack of knowledge (I only program for fun, not for a job unfortunately) so if I have to take the hard route I guess it's a learning experience, right?

回答1:

Auto unregistering listeners when an activity stops is a feature on the class "Task" in android and its derived classes (StorageTask).

This means you can do something like this:

UploadTask uploadTask = ref.putFile(uploadFile);

uploadTask.addOnFailureListener(thisActivity, new OnFailureListener() {
//@Override code here
}).addOnSuccessListener(thisActivity, new OnSuccessListener<UploadTask.TaskSnapshot>() {
//@Override code here
}).addOnProgressListner(thisActivity, new OnProgressListner<UploadTask.TaskSnapshot>() {
//@Override code here
};

You can also do this with Task objects returned from the realtime Database such as setValue as in:

databaseReference.setValue("newValue").addOnSuccessListener(thisActivity, ...)

So to answer your questions directly:

  1. Use the activity scoped version to automatically unregister the listeners on activity stop. Note that for storage, you can query running operations when your activity starts using StorageReference.getActiveUploadTasks and StorageReference.getActiveDownloadTasks and re-subscribe.

  2. You shouldn't need to unsubscribe manually if using scoped listeners. I do not know of a way to batch unsubscribe to non-task based listeners.

  3. Well I'm not sure how you can guarantee that the OS will always kill your task instead of stopping/starting it again -- and how your finish code will be guaranteed to run. I would advise you move the code to onStart