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”
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
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
in Activity just use:
in Fragment:
Instead of
getApplicationContext()
, just useActivityName.this
.Use
MyDialog md = new MyDialog(MyActivity.this.getParent());
If you are outside of the Activity then you need to use in your function "NameOfMyActivity.this" as Activity activity, example:
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: