When is mContext null-cleared? (widget, adapter etc.) - android

I'm fighting with memory leaks now.
Just out of curiosity,
when is mContext, the member of View or Adapter classes, null-cleared?
I couldn't find a part doing such a thing...
EDIT:
I know about GC, but for example,
an ArrayAdapter has mContext, and if Activity has the reference to the ArrayAdapter,
is this a circular reference?

Checking when null variables will get freed is beyond your control. But you can avoid the OOME problems.
As Dmitry said, if you are using Bitmaps, immediately call its recycle() method after use.
This way you can clear the resources you have held and make space for the application to run.
Calling GC is of no use since, even if you call it, it is not sure whether GC will free up your resources.
Also check if you have no memory leak problem in your code. Since this can also lead to OOME. You can check the memory leak problem by using MAT(plugin) for eclipse.
Even if this does not solve your problem, ask us, we'll try to find another solution.
Thank you :)

The context is generally the owning activity, which is managed by Android. It is guaranteed to be active and valid, until the Activity is active. Unless you are doing something tricky or fairly low level, you shouldn't be concerted about mContext in views and adapters.
What you should be concerned about is storing a reference to an activity (such as in a Context mContext or similar field) in a class that can potentially live longer than the activity (service, thread, application class, etc.). This will prevent the system from properly GC-ing the activity and will lead to memory leaks and subtle bugs.

It won't be cleared until garbage collector will get it. In other words - you shouldn't worry about clearing your variables, since they all will be collected by GC if there is no references to them (not instantly, but they will).
But there is one class in Android that causes troubles - Bitmap. If there is memory leaks in your app, first of all - look at bitmap usage. Make sure that you called recycle when you finished with it.

Related

How safe is MutableContextWrapper

How safe is the Android's MutableContextWrapper to use in terms of memory leak etc? I am instantiating a WebView with an Activity's context and later want to change its context to another Activity.
Here is an answer that warns of using MutableContextWrapper for WebView as it can cause leaks with mix of contexts. But i dont see any reason as how can it cause leaks when we change its context?
Why shouldnt we change a View's context once its been intialized?
Has anybody used in and faced any problems(specially for WebView)? Are there any precautionary measures while using it?Any data to share for this?
Definitely not safe. There are actions on Context that require counter-actions in order to free up resources, e.g. Context.registerComponentCallabacks, Context.registerReceiver, and if you change the Context in the meantime, that means the counter-actions will not be called for the initial context, resulting in resource leaks. And WebView uses these actions, that's for sure.
Note that WebView is a much more complex component that a regular View, because it contains a network stack, a rendering engine, etc.

Is having app context in a static member a good practice?

public class App extends Application {
public static App ctx;
#Override
public void onCreate() {
super.onCreate();
ctx = App.this;
}
}
Then in every non contextwrapper inherited class that needs a Context i use it like App.ctx, Ive been using this extensively in my apps and was wondering, is this a good practice or can it lead to memory leak or any other unexpected results?
Regarding the answer provided by Aritra Roy :
There is no guarantee that the non-static onCreate() (where you are
initializing) will be called before any static initialization which
requires the Context
according to google docs :
void onCreate() Called when the application is starting, before any
activity, service, or receiver objects (excluding content providers)
have been created.
Hence, unless your app provide services to other apps which was not my case so far, it is garunteed that any call within your application flow would come after onCreate was called. And static blocks are not called unless needed so any static block would as well be called after onCreate was called.
Your calling code needs to be ready to deal with null values coming
up because of this, which makes the entire thing more inconvenient
not relavant as App.ctx will never be null unless explicitly set to null anywhere on your own code. according to previous point.
This can lead to huge memory leaks issues
That is exactly what i was asking about, this statement can be true or false, but you didnt back it up so its useless. I was actually asking if it can lead and how can it lead to memory leaks.
Can't implement this static Context in a library project because you
can't extend the Application object.
This is incorrect as ive done it myself and it worked well.
IMO its bad practice.
Because if you context for an object or a method of an object its there for a reason and you should pass the specific context that you (Activity,Service, etc.).
I've been writing apps for 4 years and everytime i wrote/saw this type of static context was of lazyness. About the memory leaks- i havent checked it but it could lead to memory leaks. Think about it - if you create a View (i know you wont:) )or other object for example with a static context at the cuntructor (that implies that one of the members need a context attached , most likely) it wont get called by the GC even if its no longer on the activity.
I think it is okay. I have an Android library which implements the same idea (nv-android-base).
From my programming experience of 23 years, what should be blamed here is Android's library design. Although many application life-cycle models such as Applet, MIDlet and Xlet have been designed, implemented and commercially executed in this software industry so far, Android has failed to learn from the experience. Some parts of Android's library tree are terrible in design and android.context.Context is one example among such terrible parts. Android should have provided a means to get the application context from a static context.
This is a bad programming practice. I will highlight few points supporting it,
There is no guarantee that the non-static onCreate() (where you are initializing) will be called before any static initialization which requires the Context
Your calling code needs to be ready to deal with null values coming up because of this, which makes the entire thing more inconvenient
This can lead to huge memory leaks issues
Can't implement this static Context in a library project because you can't extend the Application object.

Using Static Application Context

I was having an issue with a handler returning during a screen rotation, meaning that the Activity had not been created yet and causing an error.
I solved this via this post: Static way to get 'Context' on Android?
Which sets up an application level static context to use. I wanted to know how safe this is to use and if there are any instances where I shouldn't use this, as I don't entirely understand it.
Thanks,
Kevin.
No, this is a horrible way to solve it. It means you're using the Application context instead of your Activity context, which is generally wrong and can cause memory leaks. The correct way to do this is to either check for this condition before ding anything that can cause this error, or to catch any exception caused and eat it.
Really the best way to solve this is just to turn off activity recreation on rotation which is and always has been a stupid idiotic idea by Google.
How safe is doing so?
Keeping an instance of the Application context as a singleton is completely safe, understanding as safe that you will not receive a NPE by accessing this instance. The application object is itself a singleton and there is only one per application. Even when the app is killed by the system, the Application object's onCreate() is the first call, so you will always obtain a reference to the Application context.
Can I use it for everything?
Of course, NO. The application context is a suitable context for resource management, like accessing to string values, getting the database instace and such. But it is not a good target for the Android View framework, which requires an Activity context. So, you can use it always when there is not a view related to its use. LayoutInflater, for example, will produce an error if you pass to it an Application context.
I recommend to use the Activity context always when you can, but there is some cases where passing the activity context is not an option, for example if you are creating a database instance when the application is being started.
What about the activity recreation on rotation?
Every Android developer will tell you it is a complete hell to manage this scenario, and it is better for you to lock your activity in vertical or do avoid the recreation of the activity. Beside there is not consistent way to do it across all brands and devices, there are many posts from Google Engineers advocating against doing it because it may produce serious memory leaks and layout problems. Here you have more information.
If you use application context you cannot do certain things like inflating a layout- if you pass the application Context into the LayoutInflater you will get an Exception.
Try to use a Loader instead. The result will not be pushed to the views until the Views are ready.

Android memory leak - deadly embrace

Initially I didn't pay a lot of attention to the possibility of memory leaks in Android, given the nature of managed code / garbage collection and so on. I'm thinking this might have been a bit naive. Here's the question:
Say there is an activity - MyActivity. When the OS starts it, in its onCreate() this instantiates another class (MyOtherClass) and keeps a reference to it. However say the instance of MyOtherClass also keeps a reference to the context - which happens also to be a reference to the instance of MyActivity.
Now something happens - say the screen gets rotated. OS calls the activity onDestroy() and drops the reference to that old instance of MyActivity. However, that activity instance still has a reference to an instance of MyOtherClass, which in turn has an instance to the activity.
So, am I right in thinking those two classes are going to keep each other alive for evermore?
If so, I guess possible answers are (a) don't keep a context reference, get it another way, or (b) in the activity onDestroy() drop any references it has to anything else, then it all ought to just collapse.
Java wouldn't allow cyclic links to keep each other alive (in memory). However if you have declared references static or created singleton style objects, Java won't help you there.
A good start might be reading avoiding memory leaks.

How to avoid OutofMemoryException?

Activites in my app contain fragments, which in turn contain listview/gridviews that're full of bitmap data. Eventually a user would run out of memory because views of the previous activities and their fragments don't get destroyed. So, when user has reached, say, 10th activity - 9 previous hold a plenty of bitmap data.
I'm already using weakrefences, however MAT says that some fragment's view holds reference to, for instance, Gallery which in turn holds adapter etc. So ImageViews retain alive and so do bitmaps.
So far I've experemented with completely removing fragments, removing adapters. Sometimes it works, but I wonder why should this be so complicated and if there's any simpler way to free/acquire without much coding ?
UPD
I would appreciate an example of open-source app where the same problems are challenged.
UPD2
Blueprint for most of my activities is: activity holds fragment. fragment holds AbslistView that are full of imageviews.
Thanks.
It is difficult to get it done without using up all the memory.
That requires on demand (re)loading, freeing memory on view destruction and careful design of your fragments and classes.
https://developer.android.com/training/displaying-bitmaps/index.html has some valuable information about loading images that way.
If you load all your images through some sort of asynchronous caching loader, clear the cache on onViewDestroyed or onDetached depending on your needs and don't keep other references to those bitmaps you should have removed most of your problems.
The lifecycle is pretty symmetrical (onCreate<>onDestroy, ...) so it's a good idea to null any references that you created in exactly the other side of that lifecycle part. Assuming you use appropriate places in the lifecycle you get a lot of memory management for free. In your case you should check that in case your fragments are retained you don't keep references to the Gallery or ImageViews (should only exists between onCreateView -> onDestroyView)
I would recommend keeping only that what you need in memory and destroy everything else. It is bad form to use up all available memory. I would look at the activity life cycle and understand it completely to resolve your issue:
https://developer.android.com/reference/android/app/Activity.html
I recommend watching the Memory management for Android apps Google IO 2011 presentation.
You should also examine your app's workflow to determine when you can start destroying old activities or freeing other resources.
You can also use ActivityManager.getProcessMemoryInfo() to retrieve memory usage information for your process to aid in determining whether you need to free some old resources.
If your outofmemoryexception happens in your adapter's getView method,
You could isolate the line it usually happens and surround it with a try-catch like this :
try {
// load image (or whatever your loadimage is)
mViewHolder.thumbImage.loadImage();
} catch (OutOfMemoryError e) {
// clear your image cache here if you have one
// call gc
System.gc();
// load image retry
mViewHolder.thumbImage.loadImage();
}
Its not the most elegant solution in the world but it should help.

Categories

Resources