Play animated GIFs in Android(2)

在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动画无限次播放,对于每一帧,我通过GifDecodergetFrame()方法获取的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

 

posted @ 2012-12-01 17:19  Ithouge  阅读(370)  评论(0编辑  收藏  举报