【问题标题】:Saving and loading Images from the Storage in Codename One从代号一的存储中保存和加载图像
【发布时间】:2019-09-18 10:39:51
【问题描述】:

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

以下类在模拟器中运行良好,但在真实设备上我注意到应用程序打开图像需要太多时间:我的意思是第一次加载后没有任何时间优势。

相反,我希望这个类第一次打开图像需要更多时间,然后下一次应该会快很多(因为缩放后的图像保存到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 的线程中被调用:如果我错了,请纠正我。

【问题讨论】:

    标签: codenameone


    【解决方案1】:

    创建EasyThread 的成本很高。您应该创建一个,然后像您一样使用run 方法。成功回调应该在 EDT 上。您可以使用isEDT() 方法轻松验证它。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 2020-01-07
      • 2018-11-03
      相关资源
      最近更新 更多