在Android里播放GIF动画是个有难度的话题,而且也被很多网友广泛的讨论,在这里我将结合我的开发经验以及获取到的各种资讯做一个总结,这其中主要包含有三个方法播放GIF动画,每个方法都有其优点和缺点。这一系列的每个部分将介绍这些方法。
在上一节,我们介绍了如何通过Android提供的类Movie实现GIF的播放,以及出现花屏的解决方法,详细阅读请移步:Play animated GIFs in Android(1)。
下面我将向大家介绍第二种Android播放GIF动画的方法:提取位图
在这一章,我将充分应用GifDecoder这个类,你可以从这里下载。它是完全符合开源协议的,可以放心下载使用,这个类的实现原理大致是从GIF输入流获取不同的bitmaps,你可以在你需要的时候显示的合适的位置,从而达到动画的效果。
那么接下来我们开始,在开始前,请确保你下载了这个类,并且已经将其放在了你工程的合适位置,比如说也许可以放在until包下面,万事具备,下面我们就可以创建一个类,这个类继承于ImageView,
1 public class GifDecoderView extends ImageView
然后我们实现构造方法,在这里传入一个Context 以及一个 InputStream,然后创建一个方法playGif(InputStream)去播放GIF动画,在这里方法里传入我们在构造方法里获取的InputStream。
在这里方法里面,我创建了5个成员变量:一个boolean类型的成员变量mIsPlayingGif,这个变量用于标明动画是否在播放。另一个是继承GifDecoder实现的对象,另一个是Bitmap变量,它用于存储从动画里获取的每帧的图片,一个Handler类去实现更新我们的UI,以及一个Runnable类用于组织安排将获取到的Bitmap绘画在视图上。
1 private boolean mIsPlayingGif = false; 2 3 private GifDecoder mGifDecoder; 4 5 private Bitmap mTmpBitmap; 6 7 final Handler mHandler = new Handler(); 8 9 final Runnable mUpdateResults = new Runnable() { 10 public void run() { 11 if (mTmpBitmap != null && !mTmpBitmap.isRecycled()) { 12 GifDecoderView.this.setImageBitmap(mTmpBitmap); 13 } 14 } 15 };
接下来让我们看看playGif(InputStream)方法,首先,我们要初始化mGifDecoder对象,之后读取stream以及设置mIsPlayingGif变量为true,确保我们的线程可以运行:
1 private void playGif(InputStream stream) { 2 mGifDecoder = new GifDecoder(); 3 mGifDecoder.read(stream); 4 5 mIsPlayingGif = true;
现在我们开始定义我们的线程,首先我们获取所有帧的数量,以及重复播放的次数,当方法GifDecoder.getLoopCount()返回值为0,这意味着GIF动画无限次播放,对于每一帧,我通过GifDecoder的getFrame()方法获取的Bitmap表示。然后通过定义的Handler 和 Runnable 成员变量去绘画当前Bitmap,并且通过thread 的 sleep方法,使其等待,直至获取下一帧将绘画的Bitmap。
1 new Thread(new Runnable() { 2 public void run() { 3 final int n = mGifDecoder.getFrameCount(); 4 final int ntimes = mGifDecoder.getLoopCount(); 5 int repetitionCounter = 0; 6 do { 7 for (int i = 0; i < n; i++) { 8 mTmpBitmap = mGifDecoder.getFrame(i); 9 int t = mGifDecoder.getDelay(i); 10 mHandler.post(mUpdateResults); 11 try { 12 Thread.sleep(t); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 } 17 if(ntimes != 0) { 18 repetitionCounter ++; 19 } 20 } while (mIsPlayingGif && (repetitionCounter <= ntimes)); 21 } 22 }).start();
接下来的事情就是去实现这个自定义的View,并传入要播放的GIF动画的InputStream。
总上所述,这个方法有其特点,有待读则实战测试,当然它也存在自身的缺点,
它的缺点就在于内存占用量。Bitmaps在Honeycomb设备上是保存在native heap,而不是Dalvik VM heap,所以它将一直耗尽你整个应用所能使用的最大内存,所以当你引用大量的Bitmaps的时候,garbage collector不会提示你超出了内存的限制,因为它只Dalvik VM的heap。为了避免这个,请确保在每一个Bitmap不在使用的时候调用recycle()方法。
如果你想了解其他的播放GIF的方法,也许是更适合你播放GIF的方法,那么请移步到:动画播放(3)
你可以从这个地址下载到Demo: http://code.google.com/p/animated-gifs-in-android/.
原文链接:http://www.ithouge.com/play-animated-gif-gifdecoder.html