However we however occasionally see collisions with OutOfMemory. Therefore where’s the trash collector?
I’m planning to consider one of several cases where huge things in memory can’t getting eliminated for a long duration. This example isn’t finally a memory problem — things is going to be accumulated eventually — therefore we often dismiss it. It is not better as it can certainly occasionally lead to OOM mistakes.
Possible I’m describing will be the Handler drip, which is typically found as an alert by Lint.
This really is a really basic activity. Notice that this unknown Runnable might submitted into the Handler with a long wait. We’ll operated they and rotate the telephone handful of instances, then dump memories and assess it.
We’ve got seven recreation in memory now. This really is not at all great. Let’s see precisely why GC can’t remove them.
The question we meant to bring a list of all Activities continuing to be in memory was created in OQL (Object Query Language), and that’s simple, yet effective.
Clearly, one of several recreation is actually referenced by this$0 . This is an indirect guide from the private lessons on the manager course. This$0 is referenced by callback , in fact it is next referenced by a chain of next ’s of Message back into the primary thread.
When you establish a non-static lessons inside the manager class, coffee creates an indirect reference to the proprietor
Once you post Runnable or content into Handler , it’s then stored in list of information commands referenced from LooperThread before the information was executed. Posting delayed information try a definite drip for at least the time of delay benefits. Posting immediately causes a temporary drip aswell in the event the queue of emails try huge.
Fixed Runnable Answer
Let’s you will need to tackle a memory space drip by getting gone this$0 , by transforming the unknown lessons to fixed.
Run, turn and get the memory space dump.
What, once more? Let’s see who keeps making reference to Activities .
Have a look at the base of the forest — activity are held as a regard to mContext inside mTextView your DoneRunnable class. Utilizing fixed interior courses is certainly not adequate to manage memory space leaks, but. We have to perform additional.
Fixed Runnable With WeakReference
Let’s continue using iterative fixes and get eliminate the mention of the TextView, which keeps task from becoming ruined.
Keep in mind that we are keeping WeakReference to TextView, and let’s manage, turn and dump storage.
Be mindful with WeakReferences. They may be null any kind of time time, therefore deal with all of them very first to a nearby changeable (tough resource) then examine to null before utilize.
Hooray! Singular activity instance. This solves our very own memory space issue.
Therefore for this strategy we ought to:
- Need static interior sessions (or outer tuition)
- Use WeakReference to objects manipulated from Handler / Runnable
Should you contrast this code to your preliminary rule, you may find a positive change in readability and rule clearance. The initial signal is a lot shorter and much sharper, and you’ll note that sooner, book in textView are going to be altered to ‘Done’. No reason to browse the code to understand that.
Writing this much boilerplate laws is very tedious, particularly if postDelayed is placed to a short time, like 50ms. You can find best and clearer assistance.
Cleanup All Messages onDestroy
Handler course keeps a fascinating function — removeCallbacksAndMessages – which can take null as discussion. It’ll eliminate all Runnables and emails posted to a certain handler. Let’s use it in onDestroy .
Let’s operate, rotate and dispose of storage.
Good! One example.
This approach was way better compared to the earlier one, because keeps code obvious and understandable. The sole cost will be take the time to remove all messages on activity / fragment obliterate.
You will find an additional solution which, if you’re idle just like me, you will fancy further. 🙂
The Badoo personnel came up with the fascinating idea of introducing WeakHandler – a category that behaves as Handler , it is means better.
It takes benefit of difficult and weak records to eradicate memory space leaks. I’ll describe the concept in more detail quite afterwards, but let’s go through the code initially:
Much like the initial signal besides one smaller difference — as opposed to making use of android.os.Handler , I’ve put WeakHandler . Let’s operate, turn and dump memory:
Nice, isn’t it? The code are cleaner than ever before, and memory space is clean also! 🙂
To make use of it, just add dependency your build.gradle:
And transfer they within java course:
Browse Badoo’s github page, where you are able to fork they, or learn it is provider signal https://github.com/badoo/android-weak-handler
WeakHandler. The way it operates
An important aim of WeakHandler is to keep Runnables / information hard-referenced while WeakHandler normally hard-referenced. When it could be GC-ed, all antichat reddit information should go out at the same time.
Here is an easy diagram that demonstrates differences between using normal Handler and WeakHandler to publish anonymous runnables:
Studying the top diagram, Activity helps to keep a reference to Handler , which posts Runnable (puts it into waiting line of emails referenced from bond). Things are okay except the indirect resource from Runnable to Activity . While Message is within the queue, all graphs can’t feel garbage-collected.
In contrast, during the base drawing task retains WeakHandler , which keeps Handler inside the house. When we ask they to post Runnable , it’s wrapped into WeakRunnable and posted. And so the information queue helps to keep guide merely to WeakRunnable . WeakRunnable keeps weak mention of the the required Runnable , so the Runnable are garbage-collected.
Another little strategy is that WeakHandler still helps to keep a hard regard to the specified Runnable , to avoid they from becoming garbage-collected while WeakRunnable is productive.
The side-effect of employing WeakHandler is that all messages and runnables may possibly not be accomplished if WeakHandler might garbage-collected. To avoid that, merely keep a reference to they from Activity. Once task is ready to be obtained, all graphs with WeakHandler will collected aswell.
Utilizing postDelayed in Android os requires further effort. To reach it we developed three various methods:
- Make use of a static inner Runnable / Handler with WeakReference to owner course
- Evident all messages from Handler in onDestroy of task / Fragment
- Incorporate WeakHandler from Badoo as a gold bullet
It’s for you to decide to select your favorite techniques. Another looks very reasonable, but requires some extra operate. The third try my personal preferred, certainly, nevertheless call for some focus as well — WeakHandler really should not be utilised without tough research from outdoors. And thank you so much for learning!