I have to draw a lot of objects on the game screen made of same Bitmap. So, I need to find a good way to reuse bitmap. I have a class where Bitmap is a field, and every object on the screen is an instance of this class (or its subclass). How can the best performance be achieved in this case?
Thanks for advices.
If you make the bitmap field static then only one instance exists. But in this case you need to manage drawing access to this object.
How about having a BitmapCache class which would be responsible for storing/caching/retrieving all the Bitmap objects.
Related
To draw my sprites in OpenGL i use a single backing bitmap across multiple objects, the Bitmap is reused if size is big enough or recreated if too small. Currently i am using a static Bitmap object but i think this is causing memory leaks even if i am not sure about that.
So, let's say i need a single Bitmap shared between multiple objects, what would be the best approach?
1) Use a single Bitmap as a static reference as i do
2) Use a static weakreference (even if its not suggested in the android dev page here http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html)
3) Use a singleton and then a Bitmap inside it (but this would be like 1)
4) Use an LRU cache and just creating a new bitmap every time i need it to be bigger
1,3 & 4 are essentially all the same. You create a static reference to either your Bitmap directly or to something that holds a reference. The same happens when you use the Application class to "anchor" that bitmap. That class is kept by Android alive and is in this context the same as a static reference.
Whether this is a memory leak or not depends on your definition. Leaked objects are those that are kept safe from the garbage collector by unintentional references to them. So it's certainly not a leak while you want that reference to keep your bitmap.
The problem that arises with cached data that is independent of the life of some Activity, Fragment or in more general terms "task" is that the data will keep memory occupied even if the user is never coming back to your app. The app process is kept alive until Android decides it needs the memory. That time between your last legit use of the bitmap and Android finally killing your app and thereby cleaning the memory can be seen as leak.
If we had magic powers, we could simply clean up the cache once we know that is going to happen. There are some realistic options though:
Using Android's callbacks: understanding onTrimMemory( int level )
time limits on references: e.g. https://github.com/jhalterman/expiringmap
2) is not an option. If you're trying to use WeakReference as cache, you haven't understood what that class is intended for and I honestly don't understand why it is even mentioned in the documentation (weakly referenced objects should be garbage collected as fast as possible once nobody has a strong reference anymore).
SoftReference is intended for "caching" but using it as actual cache is not only broken on Android. It's broken by design because you give the garbage collector the responsibility to maintain a cache for you without telling it how to prioritize objects or how much memory it should keep guaranteed under what conditions. The result is that the GC will clean up the wrong thing or simply everything. SoftReference can be used to in addition to a proper cache that knows how to clean up.
In addition to all of that: be aware that a single Bitmap may not be enough. If you had a look at Tasks and Back Stack you may have noticed that 1 app process can have 2 or more independent tasks in parallel. That means there could be whatever Activity uses the bitmap in different stages. If you don't want to overwrite your cache bitmap between those all the time, you may have to have 1 bitmap per task.
I don't know how to do it per task, but you can easily use a retained fragment to tie the life of your bitmap to that of an activity (ignoring screen rotation etc): http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html / example with bitmap cache https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/util/BitmapCache.java
I think best way is to create Singleton with hard reference plus some methods for recycling and loading, I've created a lot different way Bitmap and graphics loaders and this is probably most efficient and easiest for access way
public class BitmapLoader{
public static BitmapLoader bl;
private static Bitmap b=null;
public static BitmapLoader getInstance(){
if(bl==null)
bl = new BitmapLoader();
return bl;
}
public Bitmap getBitmap(Context c){
if(b==null && c!=null)
b=loadBitmapUsingContectIfNeededOrWhateverYouWant(c);
return b;
}
public void recycleBitmap(){ //for e.g. onDestroy() Activity or other
if(b!=null)
b.recycle();
}
}
keeping loaded Bitmap in LruCache is also good idea
I read about using LruCache from developer.android.com, and I create a blurred Bitmap from one activity and put it into cache, now that I want to access the cached image from another activity but it returned null. Any examples or links on how to properly use cache will be greatly appreciated, thanks!
The LruCache is being instantiated in one class. It won't be accessible from another class. You could try the approach mentioned in this answer
https://stackoverflow.com/a/14325075/2931650
I have a customview with a field(it's name is step) that set in constructor(really I pass it's values as parameter when I create an instance).Also I create some Bitmaps in constructor width of Bitmaps is correspond to that field(that comes from constructor).I know how to create Bitmaps,but I have to crate many instance of that class,so each instance has it's Bitmaps and so I will have many Bitmaps in run time that usually are same(if step field be same between classes).I thought that I can create a static class that store bitmaps,but as I said,it is possible that they be different.
Is there any way to decrease the number of Bitmaps that are created?
Sounds like a job for a Map, HashMap (or maybe WeakHashMap) in particular. The values would be the bitmaps and the keys would be the step values. Placing it in a static instance of a class is reasonable.
While reading this class BitmapFactory
I noticed that almost all methods inside are static.
Wouldn't that cause a memory exception error sooner or later?
Edit* because of another answer I am more curious of another question. Sorry for this
New question:
Would it be good practice to reuse the same class for all activities
through out the entire application?.
Reason being if a bitmap is called in lazyloading where multiple threads are created there will then be a multiple instance of the BitmapFactory classes. Thus, creating multiple Bitmapfactory methods with a return of static Bitmaps.
No, these methods don't keep data/state whatever, it's like a box, you give input, you receive result. And that's all. The only consumed memory will be the class itself which will be done only once.
is it reasonable to pass a Drawable or Bitmap across via onRetainNonConfigurationInstance() to save the expense of calling res.getDrawable() again?
You should not pass drawables. Android may choose different drawables from resources after changing orientation.
In my project i am passing only data, which i loaded from internet.
http://developer.android.com/resources/articles/faster-screen-orientation-change.html
Here is written:
Be very careful with the object you pass through onRetainNonConfigurationChange(), though. If the object you pass is for some reason tied to the Activity/Context, you will leak all the views and resources of the activity. This means you should never pass a View, a Drawable, an Adapter, etc.
Sorry for my English =)