Complex activity issues - android

I think my problem is because I'm misusing inheritance. I've got 4 activities, all extend BaseActivity which shares common code (onClick, onItemClick, static and non-static methods). Each activity get it's data from web - that includes images. When I use whole app for longer period of time I've got memory leak errors (VM won't let us allocate xxx bytes) and app crushes.
If I properly understand - it's because by extending these 4 activities I make them something like inner classes of Base Activity - that's why their onDestroy() methods aren't invoked when I switch between them. Moreover - GC don't reclaim any RAM and heap is beeing clogged. BaseActivity is holding all the data (for example images) thus allowing showing them when Back button is clicked with no need to recreating the data.
If that's true - another option is make them seperate by using helper classes to share common code - but then, when I will be switching between activities - they will be downloading it's data over and over.
I'm I right and is there any solution ?

So, it's hard to answer without seeing some code, but extending the Activity class shouldn't really be causing memory leaks. More than likely you're hanging on to a lot of unnecessary data from your web requests. You said you were downloading images, right? I'd start by looking there.

Related

android - glide bitmaps not being GC'd

Our app has the ability to chain navigation together, which is resulting in us running out of memory.
By chaining I mean we have one Activity, and a certain type of Fragment that allows you to open an instance of the same fragment type but with diff data.
e.g. Activity->MyFragment->MyFragment->MyFragment->MyFragment->MyFragment....
because of this we run out of memory eventually as this fragment has a viewpager of images plus another few images in it.
looking at the following two SO links
Android app out of memory issues - tried everything and still at a loss
When a Fragment is replaced and put in the back stack (or removed) does it stay in memory?
Diane (hackbod) highlights that you should tidy up your resources in onDestroyView, which I have done.
However, using the Memory tab in Android Monitor, and dumping the heap to hprof files, I can see that my bitmaps and imageviews never get destroyed.
I am wondering if this is something to do with Glide and the bitmapPool? I don't know how to configure this as we are only using the static Gilde.with method to get a RequestManager and I can't see any methods in that to configure bitmapPools or anything.
Any ideas?
:)

How to keep calculated data in memory for multiple activities?

My problem seemed simple to me, but apparently it isn't.
I got a core class that is able to calculate a complex result depending on parameters entered by a user. Up to now I showed the result as a ListView and for the detail view, I used a sliding panel - so everything is neat within one activity A.
But now, I wanted to get rid of the sliding design and "simply" use a master/detail flow so I could show two fragments next to each other on tablets and separately on a mobile phone.
Well, I did not want to redesign the whole app for that, but basically: how do I get the detail information to my different activity B???
I know that through an Intent I can only send Parcelable (or serializable) data, but that is far to complex for essentially int-array-type of data! All the converting to and re-constructing from the Intent - that is just a pain!
Of course, I also do not need a database or similar complicated stuff - no SharedPrefs, please, that is all at least as complex as implementing the Parcelable!
Basically, I thought of two approaches, but they all ... stink ... kind of:
a) store the calculated data within the application class - problem: the app might get destroyed and restarted just for re-displaying activity B. Then there wouldn't be anything left in the app object!
b) implement a content provider that does the calculation and caching the result there. Hmm. The cursor again is way to complex to transfer the simple result. And: for how long should I cache the result in the ContentProvider?
I feel this is all a mess. :-(
Any ideas?
The Intent approach is by far the simplest one.
Talking about a Master/Detail flow, usually that means passing one id, this is few information and easily reconstructed from A to B (activity).
Don't use A for exactly the reason you mentioned, and B wow! too much work =)
I really think either use an Intent or use shared Prefs they are by far the least code demanding options.
Have you been able to create the behavior of the app getting destroyed and everything being deleted? I've been developing an app doing some things along the same lines and I have just been using public static variables to store things in the activity that they are created in. That way they are accessible from other activities. Not necessarily the most elegant way of doing things but it's working for me just fine.
oh man its not mess:)
did you aware of Design patterns if yes then you can use singleton pattern where you can store data for your next activity
public class mySingleton
{
mySingleton instance;
yourvariable1;
yourvariable2;
yourvariable3;
yourobject1;
yourobject2;
public static mySingleton getSingletonInstance()
{
if(instance==null)
{
instance=new mySingleton();
}
return instance;
}
}
by this you can save your data till your any activity is running or you may say untill your application is in system memory
but if you want to close application and persist data then make a background service there you can save data your applications activities will destroy but the service will contain the variables and data
hope it will solve your problem

Move Sensor data to a different class/activity

I have a simple app, it logs a bunch of sensor/gps data. The first activity is a mess, and way too long, so i wanted to modularize it. I want to have 3 modules now:
Main Activity
Sensor Data (Gyroscope, accelerometer, etc)
GPS Data (Position, elevation, etc)
What is the best way for me to go about modularizing this? I was trying to move some of the Sensor Data out of the original class, and then I noticed that my class needed to extend some android.content.context (such as an Activity) in order to access the sensor data properly?
Thanks for a nudge in the right direction.
From my comments on the original question...
You don't need to extend Context - you can create helper classes and simply pass the Activity Context into the class constructor or into the various methods using this from the Activity.
As long as you design your helper classes correctly then it is fine and it is something that many people do and, indeed, there are various Android classes which require a Context parameter. Avoid memory leaks and use the right Context.
Sometimes using the application Context might be better as it is persistent for the life-time of all application components. It is, however, only a partial context in that certain things won't work with it (some UI-related tasks, for example). Otherwise using the Activity Context is fine as long as nothing holds a permanent reference to it (which can cause memory leaks if the Activity is destroyed.

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