在代号一中从存储中保存和加载图像
Saving and loading Images from the Storage in Codename One
看来我的以下代码没有按预期工作。
以下 class 在模拟器中运行良好,但在真实设备上我注意到该应用程序打开图像需要太多时间:我的意思是第一次加载后没有任何时间优势.
相反,我希望这个 class 应该需要更多时间来第一次打开图像,然后下次应该会快很多(因为缩放后的图像保存到 Storage
).
EasyThread
的目的是在缩放期间不阻塞 EDT,因为我有多个图像,总共需要很多秒 cpu。
/**
* Button useful to show the given Image at the given size.
*
* @author Francesco Galgani
*/
public class FixedSizeButton extends Button {
private final int imageWidth;
private final int imageHeight;
private FixedSizeButton instance;
private Image image;
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight) {
this(image, uniqueName, imageWidth, imageHeight, null);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param uiid
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight, String uiid) {
this(image, uniqueName, imageWidth, imageHeight, false, uiid);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param scaledSmallerRatio force the image to maintain the aspect ratio
* within the given dimension (it requires that both imageWidth and
* imageHeight are specified)
* @param uiid
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight, boolean scaledSmallerRatio, String uiid) {
if (image == null) {
throw new IllegalArgumentException("image cannot be null");
}
if (StringUtilities.isEmptyOrNull(uniqueName)) {
throw new IllegalArgumentException("image must have an unique name");
}
if (imageWidth <= 0 && imageHeight <= 0) {
throw new IllegalArgumentException("invalid imageWidth and imageHeight");
}
this.instance = this;
setShowEvenIfBlank(true);
if (uiid != null) {
super.setUIID(uiid);
}
if (imageWidth < 1) {
imageWidth = image.getWidth() * imageHeight / image.getHeight();
} else if (imageHeight < 1) {
imageHeight = image.getHeight() * imageWidth / image.getWidth();
}
if (scaledSmallerRatio) {
float hRatio = ((float) imageHeight) / ((float) image.getHeight());
float wRatio = ((float) imageWidth) / ((float) image.getWidth());
if (hRatio < wRatio) {
imageWidth = (int) (image.getWidth() * hRatio);
} else {
imageHeight = (int) (image.getHeight() * wRatio);
}
}
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
String fileName = StringUtilities.replaceAll(uniqueName, ".", "_") + "_" + this.imageWidth + "_" + this.imageHeight + ".jpg";
this.image = Image.createImage(this.imageWidth, this.imageHeight, 0xFFdddddd);
this.setIcon(this.image);
EasyThread scalingThread = EasyThread.start("FixedSizeButton-ScalingImg-" + fileName);
scalingThread.run(new RunnableWithResult<Image>() {
@Override
public void run(SuccessCallback<Image> onSuccess) {
try {
if (Storage.getInstance().exists(fileName)) {
Image scaledImg = Image.createImage(Storage.getInstance().createInputStream(fileName));
onSuccess.onSucess(scaledImg);
} else {
Image scaledImg = image.scaled(instance.imageWidth, instance.imageHeight);
ImageIO.getImageIO().save(scaledImg, Storage.getInstance().createOutputStream(fileName), ImageIO.FORMAT_JPEG, 0.9f);
onSuccess.onSucess(scaledImg);
}
} catch (IOException ex) {
Log.e(ex);
SendLog.sendLogAsync();
}
}
}, new SuccessCallback<Image>() {
@Override
public void onSucess(Image image) {
instance.image = image;
instance.setIcon(instance.image);
}
});
}
@Override
public Dimension calcPreferredSize() {
int width = imageWidth + this.getStyle().getPaddingLeftNoRTL() + this.getStyle().getPaddingRightNoRTL();
int height = imageHeight + this.getStyle().getPaddingTop() + this.getStyle().getPaddingBottom();
return new Dimension(width, height);
}
@Override
public void setText(String text) {
throw new IllegalStateException("Not supported");
}
}
我猜这里有问题:
if (Storage.getInstance().exists(fileName)) {
Image scaledImg = Image.createImage(Storage.getInstance().createInputStream(fileName));
onSuccess.onSucess(scaledImg);
} else {
Image scaledImg = image.scaled(instance.imageWidth, instance.imageHeight);
ImageIO.getImageIO().save(scaledImg, Storage.getInstance().createOutputStream(fileName), ImageIO.FORMAT_JPEG, 0.9f);
onSuccess.onSucess(scaledImg);
}
最后,我假设instance.setIcon(instance.image);
是在EDT中调用的,image.scaled
是在非EDT的线程中调用的:如果我错了请指正。
创建一个 EasyThread
很昂贵。您应该创建一个,然后像您一样使用 run
方法。成功回调应该在美国东部时间。您可以使用 isEDT()
方法轻松验证它。
我建议添加一些日志记录以确保正确缓存和加载图像。
看来我的以下代码没有按预期工作。
以下 class 在模拟器中运行良好,但在真实设备上我注意到该应用程序打开图像需要太多时间:我的意思是第一次加载后没有任何时间优势.
相反,我希望这个 class 应该需要更多时间来第一次打开图像,然后下次应该会快很多(因为缩放后的图像保存到 Storage
).
EasyThread
的目的是在缩放期间不阻塞 EDT,因为我有多个图像,总共需要很多秒 cpu。
/**
* Button useful to show the given Image at the given size.
*
* @author Francesco Galgani
*/
public class FixedSizeButton extends Button {
private final int imageWidth;
private final int imageHeight;
private FixedSizeButton instance;
private Image image;
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight) {
this(image, uniqueName, imageWidth, imageHeight, null);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param uiid
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight, String uiid) {
this(image, uniqueName, imageWidth, imageHeight, false, uiid);
}
/**
* Creates a Button displaying an Image at the given fixed size; at least
* one of imageWidth or imageHeight must be specified.
*
* @param image
* @param imageWidth in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param imageHeight in pixels, can be -1 to automatically resize
* maintaining the aspect ratio
* @param scaledSmallerRatio force the image to maintain the aspect ratio
* within the given dimension (it requires that both imageWidth and
* imageHeight are specified)
* @param uiid
*/
public FixedSizeButton(Image image, String uniqueName, int imageWidth, int imageHeight, boolean scaledSmallerRatio, String uiid) {
if (image == null) {
throw new IllegalArgumentException("image cannot be null");
}
if (StringUtilities.isEmptyOrNull(uniqueName)) {
throw new IllegalArgumentException("image must have an unique name");
}
if (imageWidth <= 0 && imageHeight <= 0) {
throw new IllegalArgumentException("invalid imageWidth and imageHeight");
}
this.instance = this;
setShowEvenIfBlank(true);
if (uiid != null) {
super.setUIID(uiid);
}
if (imageWidth < 1) {
imageWidth = image.getWidth() * imageHeight / image.getHeight();
} else if (imageHeight < 1) {
imageHeight = image.getHeight() * imageWidth / image.getWidth();
}
if (scaledSmallerRatio) {
float hRatio = ((float) imageHeight) / ((float) image.getHeight());
float wRatio = ((float) imageWidth) / ((float) image.getWidth());
if (hRatio < wRatio) {
imageWidth = (int) (image.getWidth() * hRatio);
} else {
imageHeight = (int) (image.getHeight() * wRatio);
}
}
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
String fileName = StringUtilities.replaceAll(uniqueName, ".", "_") + "_" + this.imageWidth + "_" + this.imageHeight + ".jpg";
this.image = Image.createImage(this.imageWidth, this.imageHeight, 0xFFdddddd);
this.setIcon(this.image);
EasyThread scalingThread = EasyThread.start("FixedSizeButton-ScalingImg-" + fileName);
scalingThread.run(new RunnableWithResult<Image>() {
@Override
public void run(SuccessCallback<Image> onSuccess) {
try {
if (Storage.getInstance().exists(fileName)) {
Image scaledImg = Image.createImage(Storage.getInstance().createInputStream(fileName));
onSuccess.onSucess(scaledImg);
} else {
Image scaledImg = image.scaled(instance.imageWidth, instance.imageHeight);
ImageIO.getImageIO().save(scaledImg, Storage.getInstance().createOutputStream(fileName), ImageIO.FORMAT_JPEG, 0.9f);
onSuccess.onSucess(scaledImg);
}
} catch (IOException ex) {
Log.e(ex);
SendLog.sendLogAsync();
}
}
}, new SuccessCallback<Image>() {
@Override
public void onSucess(Image image) {
instance.image = image;
instance.setIcon(instance.image);
}
});
}
@Override
public Dimension calcPreferredSize() {
int width = imageWidth + this.getStyle().getPaddingLeftNoRTL() + this.getStyle().getPaddingRightNoRTL();
int height = imageHeight + this.getStyle().getPaddingTop() + this.getStyle().getPaddingBottom();
return new Dimension(width, height);
}
@Override
public void setText(String text) {
throw new IllegalStateException("Not supported");
}
}
我猜这里有问题:
if (Storage.getInstance().exists(fileName)) {
Image scaledImg = Image.createImage(Storage.getInstance().createInputStream(fileName));
onSuccess.onSucess(scaledImg);
} else {
Image scaledImg = image.scaled(instance.imageWidth, instance.imageHeight);
ImageIO.getImageIO().save(scaledImg, Storage.getInstance().createOutputStream(fileName), ImageIO.FORMAT_JPEG, 0.9f);
onSuccess.onSucess(scaledImg);
}
最后,我假设instance.setIcon(instance.image);
是在EDT中调用的,image.scaled
是在非EDT的线程中调用的:如果我错了请指正。
创建一个 EasyThread
很昂贵。您应该创建一个,然后像您一样使用 run
方法。成功回调应该在美国东部时间。您可以使用 isEDT()
方法轻松验证它。
我建议添加一些日志记录以确保正确缓存和加载图像。