Comments (24)
BitmapDrawable keeps all (or most?) of it's state in a "State" object, that opens up some interesting opportunities:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/drawable/BitmapDrawable.java
from android-gif-drawable.
Also, maybe it's not the book keeping stuff, but the frame buffers that are causing the GC thrashing? When exactly are they allocated?
from android-gif-drawable.
I've confirmed that GifDrawables are definitely not safe to share in their current form. No crashes or anything, but subsequent ImageViews do not animate properly.
from android-gif-drawable.
Nothing is allocated at Java level during animation in GifDrawable.
I have not checked it yet but I guess that in ListView items, all Views (including its Drawables) which are not visible may be garbage-collected if there is no other references to them. I have no idea now if there is any other way to prevent GC thon keeping references.
Could you provide same sample project where you are experiencing GC thrashing?
I have also not tested single GifDrawable instance with multiple ImageViews. What do you mean by proper animation?
from android-gif-drawable.
So it's not the animation that's the problem, it's any incidental allocations during instantiation.
In ListView's the recycled views are generally not GCed during normal operation. They are given back to you to be reused. It's at this point, if I create a new instance of GifDrawable to set on the recycled ImageView, I get lots of GC activity, where as doing the same with a BitmapDrawable does not.
I will grab the location tracker data and post it.
from android-gif-drawable.
Note that I'm still using 1.0.4
OK, so this is just doing a new GifDrawable( byteArray )
each time we need to recycle an ImageView.
The two largest and most frequent allocations are the following:
32416B int[] 1 pl.droidsonroids.gif.GifDrawable <init>
at pl.droidsonroids.gif.GifDrawable.<init>(GifDrawable.java:133)
I think that was this line:
mColors = new int[ mMetaData[ 0 ] * mMetaData[ 1 ] ];
These are much smaller, but still quite frequent:
272B byte[] 1 pl.droidsonroids.gif.GifDrawable openStream
at pl.droidsonroids.gif.GifDrawable.openStream(Native Method)
at pl.droidsonroids.gif.GifDrawable.<init>(GifDrawable.java:132)
The first one seems most significant.
The both occurred ~225 times. Probably once per GifDrawable. Nothing else in the allocation report is anywhere near the size nor frequency of these two.
from android-gif-drawable.
Maybe if we could keep around a GifDrawable, but be able to swap out it's backing data, and just reset it's book keeping vars. That way no further allocation would be required, just some code to reset things for the new backing data. idk if this is the cleanest solution though.
edit: on second thought, this isn't the best solution. Really just trying to find a way to cut down on the allocations is the best if we can find a way.
from android-gif-drawable.
What about creating something like pool. Pseudo-java-code below (without thread safety, exception handling etc.):
static class GifDrawablePool
{
private final LruCache <Object, GifDrawable> mMap=<LruCache or some map>
public GifDrawable acquireFromResource(Resources res, int resId)
{
GifDrawable drw=mMap.get( resId );
if (drw!=null)
return drw;
drw=new GifDrawable( res, resId );
mMap.put( resId, drw );
return drw;
}
public GifDrawable acquireFromPath (String path)
{...
...
mMap
will cache some number of recent GifDrawable instances and its size will be controlled to prevent OutOfMemoryErrors. The best keys are immutable objects.
from android-gif-drawable.
hhmmm, I think with a sufficient number of unique entries in a data set, this is going to not yield any real gains. Maybe if there was some way of re-using them for different GIFs? But I guess the hard part is that the frame sizes will be different?
from android-gif-drawable.
We can reuse only frame buffers (mColors
arrays) because their allocation is most expensive. Given array can be used not only for equal-sized drawables but also for smaller ones. So we can create pool for int arrays which will work as written below (pseudocode):
in GifDrawable constructors:
int len=mMetaData[ 0 ] * mMetaData[ 1 ];
mColors=getArrayFromPool(len);//if array having required length or greater is available, return it with removing from pool, return null otherwise
if (mColors==null)
mColors = new int[ len ];
when GifDrawable instance is no longer needed:
addToPool(mColors)
The moment when instance is no longer needed could be eg. onDetachedFromWindow()
in GifImageView (finalize()
is not guaranteed to be called). In such case we just remember reference to frame buffer for reuse and recycle rest of the GifDrawable.
from android-gif-drawable.
Ya this could be a good solution. Maybe as a ctor argument we could accept a pool as an option. Many use cases wouldn't require this optimization, but have it be an optional parameter or something.
from android-gif-drawable.
Just found this:
http://developer.android.com/training/displaying-bitmaps/manage-memory.html
Their overall solution is extremely robust, and also extremely intricate.
But the tl;dr is: since HC they added a way to provide a Bitmap which the decoder can re-use, and just decode right into. No allocations required.
from android-gif-drawable.
We do not use Bitmap but int array as a frame buffer. Nevertheless it is good idea to use set of SoftReferences as cache container as in their example.
One little additional thing: is most efficient to reuse as small frame buffer as possible so cache may be sorted by size ascending.
from android-gif-drawable.
Besides "main" frame buffer (int
array) there is one another for color indexes at native level (having same dimensions but holding char
s instead of int
s). If at least one frame uses "restore to previous" disposal method additional buffer is required.
So taking it all together it will be better to reuse all the drawable as you said before. To achieve this we need to add GifDrawable#setInput()
method set (with arguments like in corresponding ctros) which will reset internal state, close old backing data input (if needed), open the new input using already allocated memory for buffers (optionally reallocating some parts if needed).
In such case pool will be completely separate from GifDrawable.
from android-gif-drawable.
Hi, is it possible to get each frame argb data? Now I'm doing smth like this:
public void getFrameData(int frameIndex, int[] data) {
seekTo(mGifInfoPtr, frameIndex, data);
renderFrame(data, mGifInfoPtr, mMetaData);
}
from android-gif-drawable.
@parizene your post is off-topic here. I've added separate issue for your question: #34
from android-gif-drawable.
I'm also running into an issue when trying to reuse GifDrawable's using a Volley backed network cache, and then trying to use that same GifDrawable in 2 ImageViews. When both ImageView's are visible in a ListView one or both of the gif animations are frozen (I'm assuming this is caused by having 2 ImageView's mess with a shared GifDrawable book keeping).
Instead I think I'll have to just cache the byte[] of the gif and create a new GifDrawable for each ImageView.
from android-gif-drawable.
Is there a way to clone a GifDrawable so that we reuse the same underlying allocated data, and just have the GifDrawable responsible for drawing to one ImageView. I've tried allocating a new GifDrawable from a cached byte[] but it makes scrolling through the ListView slower and I'm worried of any leaked memory that might occur.
from android-gif-drawable.
@dougnukem one GifDrawable associated with more than one view is not supported now. I'll have to add this information to Readme.
Only way to clone GifDrawable is to construct new one in the same way, exactly as you said. I can add clone()
method but it will work also similarly.
Constructing new GifDrawable is heavy and time-consuming process since frame buffer (or buffers) must be allocated. One of the ways to improve this process is to reuse instances of GifDrawable like it was described in previous posts in this issue.
I am planning to do this next week.
from android-gif-drawable.
Changes from #57 should improve the performance because decoding has been moved to background thread. Code available at experimental branch and in maven snapshot repository.
from android-gif-drawable.
The frame decode performance is not the bottle neck. It's the fact that even if you share the actual GIF data, every instance of GifDrawable must allocate it's own frame buffer, and this will cause excessive GC.
from android-gif-drawable.
Reusing of frame buffer added (in experimental branch), only for that one allocated at Java level by now. Just pass an GifDrawable instance to be reused as an extra argument for constructor. If old drawable is large enough its frame buffer will be reused and rest of it recycled.
If old drawable is larger than constructed one then extra buffer space is also available for next reusing.
from android-gif-drawable.
Introducing this feature to dev branch started. Instead bunch of constructors there is builder.
from android-gif-drawable.
Finally done. Feature available on dev branch and maven snapshot repository.
Amount of memory allocated at native level is relatively small in comparison to frame buffer (Bitmap). Additional buffer is needed only for one particular disposal method which is not used in all GIFs. So only Bitmap is tried to be reused.
from android-gif-drawable.
Related Issues (20)
- How do I disable looping? HOT 1
- Fatal Exception: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.app.my_app_package_name/app_lib/libpl_droidsonroids_gif.so" is 64-bit instead of 32-bit HOT 6
- CPU Usage when having more GifImageView's HOT 3
- Matcher for testing GifImageView with Espresso? HOT 1
- Security Hole HOT 4
- black screen phenomenon HOT 15
- Gif flickering HOT 1
- IllegalArgumentException, message: Unsupported class file major version 61. HOT 1
- java.lang.ExceptionInInitializerError HOT 5
- The abnormal invalidationDelay in RenderTask causes the animation to stop playing HOT 9
- Unsupported still image HOT 6
- proguard rule HOT 5
- Native crash fdsan_error HOT 1
- gif gets distorted HOT 1
- Regarding image transformation and changing direction HOT 1
- signal 6 code -1 HOT 1
- Getting below crash frequently in Production build HOT 2
- FORTIFY enablement HOT 1
- libpl_droidsonroids_gif.so :Java_pl_droidsonroids_gif_GifInfoHandle_openNativeFileDescriptor HOT 5
- Support 16 KB page sizes for Android 15 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from android-gif-drawable.