以代号One从存储中保存和加载图像 [英] Saving and loading Images from the Storage in Codename One

查看:77
本文介绍了以代号One从存储中保存和加载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎我的以下代码未按预期工作。

It seems that my following code doesn't work as expected.

以下类在Simulator中工作正常,但在实际设备上,我注意到该应用程序需要打开图像的时间太多:我的意思是第一次加载后没有任何时间优势。

The following class works fine in the Simulator, but on real devices I noted that the app takes too much time to open the images: I mean that there isn't any time advantage after the first load.

相反,我希望此类需要更多时间才能打开第一次,然后再下一次应该更快(因为缩放后的图像将保存到 Storage )。

Instead I expect that this class should require more time to open an image the first time, and then it should be a lot faster next times (because the scaled image is saved to the Storage).

EasyThread 的目的是在缩放过程中不阻塞EDT,因为我有多张图像,总共需要很多秒

The purpose of the EasyThread is to don't block the EDT during the scaling, because I have multiple images that in total can require a lot of seconds of 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的线程中被调用:如果我是错的。

Finally, I assume that instance.setIcon(instance.image); is called in the EDT and image.scaled is called in a thread that is not the EDT: please correct me if I'm wrong.

推荐答案

创建 EasyThread 是昂贵的。您应该先创建一个,然后再使用 run 方法。成功回调应该在EDT上。您可以使用 isEDT()方法轻松验证它。

Creating an EasyThread is expensive. You should create one and then use the run method as you do. The success callback should be on the EDT. You can easily verify it using the isEDT() method.

我建议添加一些日志记录以确保图像已缓存并正确加载。

I suggest adding some logging to make sure that the image is cached and loaded correctly.

这篇关于以代号One从存储中保存和加载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆