My Activity is trying to create an AlertDialog which requires a Context as a parameter. This works as expected if I use:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
However, I am leery of using "this" as a context due to the potential for memory leaks when Activity is destroyed and recreated even during something simple like a screen rotation. From a related post on the Android developer's blog:
There are two easy ways to avoid context-related memory leaks. The most obvious one is to avoid escaping the context outside of its own scope. The example above showed the case of a static reference but inner classes and their implicit reference to the outer class can be equally dangerous. The second solution is to use the Application context. This context will live as long as your application is alive and does not depend on the activities life cycle. If you plan on keeping long-lived objects that need a context, remember the application object. You can obtain it easily by calling Context.getApplicationContext() or Activity.getApplication().
But for the AlertDialog()
neither getApplicationContext()
or getApplication()
is acceptable as a Context, as it throws the exception:
"Unable to add window — token null is not for an application”
per references: 1, 2, 3, etc.
So, should this really be considered a "bug", since we are officially advised to use Activity.getApplication()
and yet it doesn't function as advertised?
Jim
Instead of getApplicationContext()
, just use ActivityName.this
.
Using this
did not work for me, but MyActivityName.this
did. Hope this helps anyone who could not get this
to work.
You can continue to use getApplicationContext()
, but before use, you should add this flag: dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
, and the error will not show.
Add the following permission to your manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
You've correctly identified the problem when you said "... for the AlertDialog() neither getApplicationContext() or getApplication() is acceptable as a Context, as it throws the exception: 'Unable to add window — token null is not for an application'"
To create a Dialog, you need an Activity Context or a Service Context, not an Application Context (both getApplicationContext() and getApplication() return an Application Context).
Here's how you get the Activity Context:
(1) In an Activity or a Service:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) In a Fragment:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Memory leaks is not a problem that is intrinsic to the "this" reference, which is an object's reference to itself (i.e. reference to the actual allocated memory for storing the object's data). It happens to any allocated memory for which the Garbage Collector (GC) is unable to free up after the allocated memory has outlived its useful lifespan.
Most of the time, when a variable goes out of scope, the memory will be reclaimed by the GC. However, memory leaks can occur when the reference to an object held by a variable, say "x", persists even after the object has outlived its useful lifespan. The allocated memory will hence be lost for as long as "x" holds a reference to it because GC will not free up the memory for as long as that memory is still being referenced. Sometimes, memory leaks are not apparent because of a chain of references to the allocated memory. In such a case, the GC will not free up the memory until all references to that memory have been removed.
To prevent memory leaks, check your code for logical errors that cause allocated memory to be referenced indefinitely by "this" (or other references). Remember to check for chain references as well. Here are some tools you can use to help you analyze memory use and find those pesky memory leaks:
JRockit Mission Control
JProbe
YourKit
AD4J
Your dialog should not be a "long-lived object that needs a context". The documentation is confusing. Basically if you do something like:
static Dialog sDialog;
(note the static)
Then in an activity somewhere you did
sDialog = new Dialog(this);
You would likely be leaking the original activity during a rotation or similar that would destroy the activity. (Unless you clean up in onDestroy, but in that case you probably wouldn't make the Dialog object static)
For some data structures it would make sense to make them static and based off the application's context, but generally not for UI related things, like dialogs. So something like this:
Dialog mDialog;
...
mDialog = new Dialog(this);
Is fine and shouldn't leak the activity as mDialog would be freed with the activity since it's not static.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With