加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Java中的双缓存技术

(2014-04-16 13:32:02)
标签:

it

分类: Java/Android

已经停滞在双缓存显示图片这一段时间了,因为代码运行出现了意外,一直想寻求解决的办法,最终找到的方法让我对这个技术颇感到失望。

首先描述下问题,先看下面一段代码:

//双缓存应用

import java.applet.Applet;

import java.awt.*; 

import java.awt.Graphics; 

import java.awt.Image;

 

public class Media extends Applet {

        

         private Image deitel[];

         private Graphics gContext;

         private Image buffer;

        

         public void init(){

                

                   deitel = new Image[ 5 ];

                   for( int i = 0; i < 5; i ++ ){

                   deitel[ i ] = getImage( getDocumentBase(), i%2+".jpg" );

                   System.out.print( "图片加载结果为: i  " + ( i % 2) + "\n"  );

 

                   }

                  

                   buffer = createImage( ( int ) getSize().getWidth( ), ( int ) getSize().getHeight( )  );

                   gContext = buffer.getGraphics();

                  

                   gContext.setColor( Color.white );

                   gContext.fillRect( 0,  0,  ( int ) getSize().getWidth( ), ( int ) getSize().getHeight( ) );

                  

         }

        

        

         public void start(){

                  

                   gContext.drawImage( deitel[ 0 ], 0, 0,

                                     ( int )(deitel[ 0 ].getWidth( this )*getSize().getHeight()/deitel[ 0 ].getHeight( this ))

                , ( int ) getSize().getHeight(), this );

                  

                  

         }

        

         public void paint( Graphics g ){

                  

                  

                  

                   for( int i = 0; i < 5; i++ ){

                            //适配显示框的高度,绘制等比例缩放的图片

                            g.drawImage( buffer,  0,  0, ( int ) (buffer.getWidth( this )*getSize().getHeight()/buffer.getHeight( this ))

                    , ( int ) getSize().getHeight(), this );

                           

                       //清空缓存

                            gContext.fillRect( 0,  0, ( int ) getSize().getWidth( ), ( int ) getSize().getHeight() );

                            //绘制下一幅图

                            gContext.drawImage( deitel[ ( i + 1 ) % 5 ],  0,  0,

                                               ( int )(deitel[ ( i + 1 ) % 5 ].getWidth( this )*getSize().getHeight()/deitel[ ( i + 1 ) % 5 ].getHeight( this ))

                                                                              , ( int ) getSize().getHeight(), this );

                        try{

                                 Thread.sleep( 200 );

                        }

                        catch( InterruptedException e ){

                                 showStatus( e.toString() );

                        }

                       

                     

                        }

                       

                  

         }

 

}

 

采用双缓存技术的标准流程一般如下:

首先需要两个对象变量,一个是Image对象(这个例子中变量名为buffer),一个是Graphics对象(这个例子中变量名为gContext),然后用下列两个语句俩创建图形双缓存:

buffer = createImage( int width, int height);

gContext = buffer.getGraphics();

第一个语句是创建大小为width*height的图像,这也就是在动画中需要显示的图片大小,第二语句则是获取Image对象对应的绘图的环境的。第二句没有问题,问题就出现在第一句上,显示动画的时候,如果并不知道需要显示图片的大小呢?看到有推荐使用如下语句的:

buffer = createImage( picture.getWidth(), picture.getHeight() )

其中pictureImage的对象,就是需要显示的图片对象,但是这样带来一个问题,就算在之前运行了

picture = getImage( getDocumentBase(), ImageLocation )

这样的语句,再运行前面所述语句,其返回的宽度和高度的数值依旧是-1,查询API后发现,返回-1的数值说明,图片没有完全的加载,那么这样很快就会有一个问题,就是图片神马时候才加载完成,看到相关的资料显示,Java的图片加载和绘制是一个异步的过程,貌似在图片draw的时候才会加载,至于加载完成,天知道?

那么就没有解决办法了吗?解决办法还是有的,Java在图片加载中提供了一个MediaTracket类,可以用来监视图片的加载,用MediaTracket的对象调用waitforID( int ID )的方法就可以监视编号为ID的图片加载完成,其主要步骤如下:

MediaTraker ImageMediaTraker; //新建MediaTraker对象

//创建对象,并指定o为图片需要绘制的对象(一般用this

ImageMediaTraker = new  MediaTraker( ImageObserver o );

//在加载图片的后面附上语句

ImageMediaTraker.addImage(image picture, int ID );

//指定等待对应ID图片加载完毕

ImageMediaTraker.waitForID( int ID);

运用上述技术,就可以保证图片在自己需要的时候加载完毕了,但是这样有一个小问题,就是由于buffercreateImage后就保持大小不变了,一旦动画显示的图片的大小规格不是一样的,那么后续过程会出现图片显示不完全的现象,虽然这样的例子在真正显示动画的时候很少,但是我做测试的时候还是遇到了,解决的办法是神马呢,那就是在每次显示了buffer图片后,重新用buffer调用一次createImage方法,并让Graphics对象重新获取一次绘图环境,也就是重新运行下列语句

buffer = createImage( int width, int height);

gContext = buffer.getGraphics();

上述这个小问题是我自己纠结了,一般动画显示的图片大小是一致的,但是看到有给出的示例,createImage中使用的长宽是就是applet或者是对话框的大小的,这个问题就凸显了,其实将createImage中使用对话框大小的貌似占大多数,那么为了确保图片的显示正确那么,必须每次加载了缓存后,重新创建缓存大小,或者接收对话框变化的通知后,重建缓存大小,或者保持绘图的大小区域一直不变,这样才能确保显示正确。

 

但是需要注意的是,createImage中使用对话框的大小,并且是使用初始化的时候对话框的大小(不使用固定对话框大小铁定会发生问题),显示图片也会出现问题,因为无法做到适配显示,所以可能会出现图片显示只出现一部分的情况,这说明图片无法适配显示高度,也就是无法做到等比例显示,那么这个时候还得想别的方法。

啰嗦了一大堆,就是想说明两个问题,使用双缓存,缓存大小选取要谨慎;Java图片加载与显示是异步的,其图片加载完成,可能是在显示的时候,如需显示之前就加载完毕,需要一个MediaTracker的监视器来监视。

双缓存技术看似很容易,用起来却有些麻烦,大家且用且珍惜。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有