-
Notifications
You must be signed in to change notification settings - Fork 6.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how to combine android-gif-drawable with glide #805
Comments
You can squeeze it through Glide's pipeline and take benefit from networking and caching: // at usage it's as simple as:
glide.load(url).into(imageView);
// make this a field and initialize it once (this is good in list adapters or when used a lot)
GenericRequestBuilder<String, InputStream, byte[], GifDrawable> glide = Glide
.with(context)
.using(new StreamStringLoader(context), InputStream.class)
.from(String.class) // change this if you have a different model like a File and use StreamFileLoader above
.as(byte[].class)
.transcode(new GifDrawableByteTranscoder(), GifDrawable.class) // pass it on
.diskCacheStrategy(DiskCacheStrategy.SOURCE) // cache original
.decoder(new StreamByteArrayResourceDecoder()) // load original
; (transcode happens after decode, but in code you can't reorder them) And the two classes you need to fill the gaps: public class StreamByteArrayResourceDecoder implements ResourceDecoder<InputStream, byte[]> {
@Override public Resource<byte[]> decode(InputStream in, int width, int height) throws IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer)) != -1) {
bytes.write(buffer, 0, count);
}
return new BytesResource(bytes.toByteArray());
}
@Override public String getId() {
return getClass().getName();
}
}
public class GifDrawableByteTranscoder implements ResourceTranscoder<byte[], GifDrawable> {
@Override public Resource<GifDrawable> transcode(Resource<byte[]> toTranscode) {
try {
return new DrawableResource<GifDrawable>(new GifDrawable(toTranscode.get()));
} catch (IOException ex) {
Log.e("GifDrawable", "Cannot decode bytes", ex);
return null;
}
}
@Override public String getId() {
return getClass().getName();
}
} |
@TWiStErRob public class GifDrawableByteTranscoder implements ResourceTranscoder<byte[], pl.droidsonroids.gif.GifDrawable> {
@Override
public Resource<pl.droidsonroids.gif.GifDrawable> transcode(Resource<byte[]> toTranscode) {
try {
// because DrawableResource is an abstract class , so i used MyDrawableResource
return new MyDrawableResource(new pl.droidsonroids.gif.GifDrawable(toTranscode.get()));
} catch (IOException ex) {
Log.e("GifDrawable", "Cannot decode bytes", ex);
return null;
}
}
@Override
public String getId() {
return getClass().getName();
}
static class MyDrawableResource extends DrawableResource<pl.droidsonroids.gif.GifDrawable> {
public MyDrawableResource(pl.droidsonroids.gif.GifDrawable drawable) {
super(drawable);
}
@Override public int getSize() {
return (int) drawable.getInputSourceByteCount();
}
@Override public void recycle() {
drawable.stop();
drawable.recycle();
}
}
} And i also add the uses-permission to write and read EXTERNAL_STORAGE .
and then if use diskCacheStrategy(NONE) ,it's error message is:
If you know the solution, please help me,thanks! |
Hmm, weirdly I didn't get an error for Yes, I forgot, that .sourceEncoder(new StreamEncoder()) it helps to cache the stream coming from the internet so you can even view the images offline later or they'll just simply load faster. Re return (T) drawable.getConstantState().newDrawable(); Also see the huge comment on it. Note that the default drawable implementation returns null, so the drawable integrated with class MyDrawableResource implements Resource<GifDrawable> {
// ... other methods and storage
@Override public GifDrawable get() { return this.drawable; }
} |
@TWiStErRob Thank you for your patience to help! .cacheDecoder(new FileToStreamDecoder<byte[]>(new StreamByteArrayResourceDecoder())) and my all code is like that: // make this a field and initialize it once (this is good in list adapters or when used a lot)
GenericRequestBuilder<String, InputStream, byte[], GifDrawable> glide = Glide
.with(context)
.using(new StreamStringLoader(context), InputStream.class)
.from(String.class) // change this if you have a different model like a File and use StreamFileLoader above
.as(byte[].class)
.transcode(new GifDrawableByteTranscoder(), GifDrawable.class) // pass it on
.diskCacheStrategy(DiskCacheStrategy.SOURCE) // cache original
.decoder(new StreamByteArrayResourceDecoder()) // load original
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<byte[]>(new StreamByteArrayResourceDecoder()));
// just load local gif , even your picture suffix is jpg or png , it also can treate it as gif to show
GenericRequestBuilder<File, InputStream, byte[], GifDrawable> glideLocal = Glide
.with(context)
.using(new StreamFileLoader(context), InputStream.class)
.from(File.class) // change this if you have a different model like a File and use StreamFileLoader above
.as(byte[].class)
.transcode(new GifDrawableByteTranscoder(), GifDrawable.class) // pass it on
.diskCacheStrategy(DiskCacheStrategy.SOURCE) // cache original
.decoder(new StreamByteArrayResourceDecoder()) // load original
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<byte[]>(new StreamByteArrayResourceDecoder()));
String localGifUrl = Environment.getExternalStorageDirectory().toString() + "/bfc.jpg";
File file = new File(localGifUrl);
if (file.exists() && file.isFile()) {
glideLocal.load(file).into(network_gifimageview0);
}
// at usage it's as simple as:
//glide.load(path0).into(network_gifimageview0);
glide.load(path1).into(network_gifimageview1);
glide.load(path2).into(network_gifimageview2);
glide.load(path3).into(network_gifimageview3);
glide.load(path4).into(network_gifimageview4); And the fixed drawable resource: static class MyDrawableResource implements Resource<pl.droidsonroids.gif.GifDrawable> {
private pl.droidsonroids.gif.GifDrawable drawable;
public MyDrawableResource(pl.droidsonroids.gif.GifDrawable gifDrawable) {
this.drawable = gifDrawable;
}
@Override
public GifDrawable get() {
return drawable;
}
@Override
public int getSize() {
return (int) drawable.getInputSourceByteCount();
}
@Override
public void recycle() {
drawable.stop();
drawable.recycle();
}
} I also found that it was more slowly than the way using |
Nice, well done. You're now an advanced user. All this (and more) is hidden behind the curtains when you call the usual simple You can get rid of the duplicate code if you use Regarding speed: it may be the cache, Glide saves input to SOURCE cache first and the starts loading from there, this is for consistency. You can use NONE if that's what you want, but beware that future loads will go to the network again. You have to decide if you can live with the initial slowness to have it faster later. Mind you for local files it's not advised to use SOURCE cache as it just copies the file on the SD card. You could also skip the file existence checks, Glide will silently fail if it can't load: leaving the ImageView empty if the file is not there or invalid. Those two checks are blocking I/O, which you shouldn't do on UI thread. Incorporating all my comments, consider: GenericRequestBuilder<String... glide = // that long Glide init
String localGifUrl = Environment.getExternalStorageDirectory().toString() + "/bfc.jpg";
glide.clone().discCacheStrategy(NONE).load(localGifUrl).into(network_gifimageview0);
glide.clone().load(path1).into(network_gifimageview1);
... This way you get caching where it's needed. |
@TWiStErRob |
Thank you guys. This info is very useful! I think that we can even move it to Wiki! |
When used above methods in recyclerview, not all images are animating. |
@ranjit-parity you should load each gif with some unique string. You can just add some random string at the end of url with unique param |
@favn1585 I dont think that's correct solution, why would i change my gif url. |
We had the same issue and we fix it by complete url with postId. So it's not random url for each row |
@favn1585 Your way works but is slowing down the loading time, takes more time to load image than before, can you suggest more alternatives? |
It cannot slow down loading time. This is just because you load each image for different url even if you have 2 same images in neighbour items. I spend some time on it a this is the only solution that we have for now |
@ranjit-parity @favn1585's url hacking (equiv API is As I see it now, you cannot fix this inside Glide, nor really work around it. The GifDrawable needs to be fixed, to support the Android contracts. As an alternative you can try to implement "cloning" outside the Note that all this started, because this use case is trying to integrate a library with Glide, which supports the same features (loading from different sources). Essentially in this use case you're using Glide as a networking library, and the using another library to visualize what you've downloaded. Glide does not support this use case in all cases and my above code is more of a demonstration of the power of the Glide API. Whenever I use the word "squeeze" it means a workaround for something that potentially has better alternative solutions. |
@TWiStErRob I'm going with snapshot-4.0 version and its doing great. So using glide for final code changes. |
Hi I am using Glide to load GIFs in my app on a recycler view and it was laggy when using vanilla Glide so I ended up with this thread and now GIFs load super fast.
And I load GIfs like this,
Now I want to load the thumbnail of the GIF before it downloads the actual GIF but I am not able to add .thubmnail to the GenericRequestBuilder glide object.
I want to add thumbnails like mentioned in the below threads, https://futurestud.io/tutorials/glide-placeholders-fade-animations |
================ when facing the problem of using same gif url in list, the above solution seems not work, so i tried anothor way to solve the problem:
then load gif to imageview like this
when Glide select the decoder,it will iterate all the candidates ,in
when animate not canceled and byteArray begins with gif feature , handles will return true and the gif decoder will be selected |
I want to decode gif by android-gif-drawable, but load picture with glide.
android-gif-drawable can pass byte array to decode gif and my code is:
and I use path url to test, it can display normal. Then I use glide to decode the same path url.
My code is this:
No matter the first way or the second way, pictures can't display.
The text was updated successfully, but these errors were encountered: