Eclipse中如何管理图像资源

Eclipse中最为人所垢病的莫过于它的SWT,特别是对于那些习惯使用Swing开发界面的程序员而言,SWT除了在速度上优于Swing,扩展性,灵活性,都远逊于Swing,特别是已经习惯于JVM代为管理资源的程序员,在面对SWT中的各种需要手工Dispose的资源,难免头大,虽然SWT对于Component一级的资源释放控制的很好,当父控件被Dispose,所有的子控件都会被释放,已经大大减少了内存泄露的机率,但对于Color,Image,以及Font,SWT并没有提供好的管理方式,特别是应用最为广泛的Image,很多时候它会带来麻烦,甚至让整个系统crash。
接下来的内容,会详细的描述如何管理Image资源,包括它的创建,销毁,以及相应的责任人。
在SWT中,Image有三个最重要的类,分别是:
org.eclipse.swt.graphics.Image
org.eclipse.swt.graphics.ImageData
org.eclipse.jface.resource.ImageDescriptor
其中清白的是ImageData和ImageDescriptor,前者就是一个比较纯粹的数据模型,描述了每张图片上某一个点的颜色等基本图形信息,而后者则扮演了一个创建工厂的角色,可以创建Image。
最让开发人员头疼的资源管理其实集中在Image类中,它会持有操作系统UI的句柄,如果过多的使用而不翻译,就会造成当前系统的句柄不足,从而出错。如果你不幸的看到org.eclipse.swt.SWTError: No more handles 这样一个异常,那么Image就是造成这一切的元凶。但Image只是一把锋利的刀,用得不好,其实还是我们程序员的过错,下面先给出应用Image和ImageDescriptor的场景。
在SWT中有一个基本的原则,谁创建资源谁释放资源。那么就是说谁创建了Image,那么谁就应该负责释放资源。但是许多程序员并不很清楚这一原则,以如下两个场景为例:
 
场景一(通过LabelProvider为Tree提供Image)
private ImageDescriptor myImageDescriptor=.....;
    public Image getImage(Object element) {
        returnmyImageDescriptor.createImage();
    }
 
请注意上面的代码,在使用myImageDescriptor.createImage()创建了一个Image以后,这个Image作为返回值,交给了TreeViewer,它再也没有回来,也就是说你给出了Image,但没有持有它,这样自然就无法销毁它,当这个方法被调用几百或者上千次的时候,就会因为原先多次创建的Image占用了大量的Handle,从而无法再得到新的Hanlde,最终导致org.eclipse.swt.SWTError: No more handles异常的抛出。
 
因此,要区分场景来应用Image和ImageDescriptor.,前者如果是开发人员自己创建的,就一定要持有它,并在合适的时候销毁它。如果是ImageDescriptor,就可以放心的交给第三方处理。
但如果经常的销毁Image,也会带来一定的性能损失,所以在 Eclipse中,经常使用ImageRegistry来缓存图片。
为了更好的帮助开发人员使用Image和ImageDescriptor,在UI框架中提供了一个PooledImageDescriptor,它扮演与ImageRegistry相近的角色,
它同样是继承了ImageDescriptor,但它与常用的ImageDescriptor有一个区别,就是它在createImage方法中,其实每次都是使用相同的Image,这样就减少了资源泄露的可能性。但是请注意,由于它只持有一个有效的Image,所以在需要ImageDescriptor的场所,不要直接使用PooledImageDescriptor,而是通过getImageDescriptor方法取得新的ImageDescriptor来使用,这是因为象Action之类的对象,会使用ImageDescriptor来createImage,再自行销毁,如果有A,B两个Action同时使用一个PooledImageDescriptor,然后各自使用PooledImageDescriptor创建了相应的Image,因为PooledImageDescriptor只有一个Image,所以这两个Action是共享一个Image,如果A先dispose了这个Image,那么B再使用这个Image就会出现问题。
所以对于PooledImageDescriptor的使用原则如下:
v 如果你需要Image,就直接使用PooledImageDescriptor的createImage,由它替你缓存Image。
v 如果你需要ImageDescriptor,请使用PooledImageDescriptor的getImageDescriptor,而不是直接将PooledImageDescriptor传递给第三方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值