Util.downloadImageToStorage vs URLImage.createToStorage vs ImageDownloadService.createImageToStorage

83 views
Skip to first unread message

Bryan Buchanan

unread,
Jun 27, 2016, 4:07:06 AM6/27/16
to CodenameOne Discussions
I noticed that ImageDownloadService is deprecated in favour of either of the other functions, but I cannot get them to work.

I have this code:

   @Override
   
protected void onShowCompleted() {

       
super.onShowCompleted();

       
/**
         * download thumbnails to display in list
         */

       
int n = CommonContext.INSTANCE.getPartsmodel().getSize();

       
for (int i = 0; i < n; i++) {
           
final Part part = (Part) CommonContext.INSTANCE.getPartsmodel().getItemAt(i);

           
String url = CommonContext.INSTANCE.getTHUMBURL() + part.getUrl();

           
// this gives EDT violation
           
           
EncodedImage placeholder = EncodedImage.createFromImage(Image.createImage(100, 100, 0xffff0000), true);
           
URLImage background = URLImage.createToStorage(placeholder, part.getUrl(), url);
            background
.fetch();
           
           
// this does not - but get EOF on read
           
           
Util.downloadImageToStorage(url, part.getUrl(), new SuccessCallback<Image>() {
               
@Override
               
public void onSucess(Image value) {
               
}
           
});

           
// this works
           
           
ImageDownloadService.createImageToStorage(url, new ActionListener() {
               
public void actionPerformed(ActionEvent evt) {
                   
/**
                     * don't need to do anything, just save
                     */

               
}
           
}, part.url);

           
if (!keep_downloading) {
               
break;
           
}
       
}


I've got a custom list cell renderer which uses the thumb nail images:

   @Override
   
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {

       
final Part part = (Part) value;

        code
.setText(part.getKey());
        price
.setText("$" + new Money(part.getSell()).toString() + "/" + part.getUnit());
        desc
.setText((String) part.getDescription());

       
if (Storage.getInstance().exists(part.getUrl())) {
           
EncodedImage myimage = EncodedImage.create((byte[]) Storage.getInstance().readObject(part.getUrl()));
            image
.setIcon(myimage);
       
} else {
            image
.setIcon(blank);
       
}

       
return this;
   
}

ImageDownloadService works as I want, but the other two either give an EDT violation, or a get an EOF read error on storage. i.e.

--------------------------------------------------------
Util.downloadImageToStorage(url, part.getUrl(), new SuccessCallback<Image>() {
    @Override
    public void onSucess(Image value) {
    }
});

get this:

java.io.EOFException
    at java.io.DataInputStream.readBoolean(DataInputStream.java:244)
    at com.codename1.io.Util.readObject(Util.java:532)
    at com.codename1.io.Storage.readObject(Storage.java:256)
    at com.webbtide.tpd.faultcodes.PartsListCellRenderer.getListCellRendererComponent(PartsListCellRenderer.java:88)
    at com.codename1.ui.List.paint(List.java:1315)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1308)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Container.paint(Container.java:1317)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1314)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Container.paint(Container.java:1317)
    at com.codename1.ui.Form.paint(Form.java:3113)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1314)
    at com.codename1.ui.Form.internalPaintImpl(Form.java:3123)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Component.paintInternal(Component.java:1231)
    at com.codename1.ui.Component.paintComponent(Component.java:1516)
    at com.codename1.ui.Dialog.initDialogBgPainter(Dialog.java:1931)
    at com.codename1.ui.Form.showModal(Form.java:1796)
    at com.codename1.ui.Dialog.showModal(Dialog.java:1048)
    at com.codename1.ui.Dialog.show(Dialog.java:516)
    at com.codename1.ui.Dialog.showPackedImpl(Dialog.java:1350)
    at com.codename1.ui.Dialog.showPacked(Dialog.java:1258)
    at com.codename1.ui.Dialog.showImpl(Dialog.java:1004)
    at com.codename1.ui.Dialog.show(Dialog.java:982)
    at com.codename1.ui.Dialog.show(Dialog.java:938)
    at com.codename1.ui.Dialog.show(Dialog.java:727)
    at com.codename1.ui.Dialog.show(Dialog.java:680)
    at com.codename1.ui.Dialog.show(Dialog.java:645)
    at com.codename1.ui.Dialog.show(Dialog.java:586)
    at com.codename1.ui.Dialog.show(Dialog.java:741)
    at com.codename1.ui.Display.mainEDTLoop(Display.java:1009)
    at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
    at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
java.lang.NullPointerException
    at com.codename1.ui.EncodedImage.create(EncodedImage.java:264)
    at com.webbtide.tpd.faultcodes.PartsListCellRenderer.getListCellRendererComponent(PartsListCellRenderer.java:88)
    at com.codename1.ui.List.paint(List.java:1315)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1308)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Container.paint(Container.java:1317)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1314)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Container.paint(Container.java:1317)
    at com.codename1.ui.Form.paint(Form.java:3113)
    at com.codename1.ui.Component.internalPaintImpl(Component.java:1314)
    at com.codename1.ui.Form.internalPaintImpl(Form.java:3123)
    at com.codename1.ui.Component.paintInternalImpl(Component.java:1288)
    at com.codename1.ui.Component.paintInternal(Component.java:1263)
    at com.codename1.ui.Component.paintInternal(Component.java:1231)
    at com.codename1.ui.Component.paintComponent(Component.java:1516)
    at com.codename1.ui.Dialog.initDialogBgPainter(Dialog.java:1931)
    at com.codename1.ui.Form.showModal(Form.java:1796)
    at com.codename1.ui.Dialog.showModal(Dialog.java:1048)
    at com.codename1.ui.Dialog.show(Dialog.java:516)
    at com.codename1.ui.Dialog.showPackedImpl(Dialog.java:1350)
    at com.codename1.ui.Dialog.showPacked(Dialog.java:1258)
    at com.codename1.ui.Dialog.showImpl(Dialog.java:1004)
    at com.codename1.ui.Dialog.show(Dialog.java:982)
    at com.codename1.ui.Dialog.show(Dialog.java:938)
    at com.codename1.ui.Dialog.show(Dialog.java:727)
    at com.codename1.ui.Dialog.show(Dialog.java:680)
    at com.codename1.ui.Dialog.show(Dialog.java:645)
    at com.codename1.ui.Dialog.show(Dialog.java:586)
    at com.codename1.ui.Dialog.show(Dialog.java:741)
    at com.codename1.ui.Display.mainEDTLoop(Display.java:1009)
    at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
    at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
[EDT] 0:0:0,0 - java.lang.NullPointerException
[EDT] 0:0:0,1 - java.lang.NullPointerException

---------------------------------------------------------------------------------------------------

EncodedImage placeholder = EncodedImage.createFromImage(Image.createImage(100, 100, 0xffff0000), true);
URLImage background = URLImage.createToStorage(placeholder, part.getUrl(), url);
background.fetch();
           
get this:

com.codename1.impl.javase.JavaSEPort$EDTViolation: EDT Violation Stack!
    at com.codename1.impl.javase.JavaSEPort.checkEDT(JavaSEPort.java:523)
    at com.codename1.impl.javase.JavaSEPort.getRGB(JavaSEPort.java:3747)
    at com.codename1.impl.javase.JavaSEPort.scaleArray(JavaSEPort.java:3979)
    at com.codename1.impl.javase.JavaSEPort.scale(JavaSEPort.java:3963)
    at com.codename1.ui.Image.scale(Image.java:1007)
    at com.codename1.ui.Image.scaledImpl(Image.java:953)
    at com.codename1.ui.Image.scaled(Image.java:918)
    at com.codename1.ui.Image.scaledLargerRatio(Image.java:902)
    at com.codename1.ui.URLImage$ScaleToFill.adaptImage(URLImage.java:103)
    at com.codename1.ui.URLImage$DownloadCompleted.run(URLImage.java:187)
    at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:103)
    at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:140)
    at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
com.codename1.impl.javase.JavaSEPort$EDTViolation: EDT Violation Stack!
    at com.codename1.impl.javase.JavaSEPort.checkEDT(JavaSEPort.java:523)
    at com.codename1.impl.javase.JavaSEPort.getRGB(JavaSEPort.java:3747)
    at com.codename1.impl.javase.JavaSEPort.scaleArray(JavaSEPort.java:3979)
    at com.codename1.impl.javase.JavaSEPort.scale(JavaSEPort.java:3963)
    at com.codename1.ui.Image.scale(Image.java:1007)
    at com.codename1.ui.Image.scaledImpl(Image.java:953)
    at com.codename1.ui.Image.scaled(Image.java:918)
    at com.codename1.ui.Image.scaledLargerRatio(Image.java:902)
    at com.codename1.ui.URLImage$ScaleToFill.adaptImage(URLImage.java:103)
    at com.codename1.ui.URLImage$DownloadCompleted.run(URLImage.java:187)    at com.codename1.ui.URLImage$DownloadCompleted.run(URLImage.java:187)


I'm obviously doing something wrong, but can't figure it out.

Shai Almog

unread,
Jun 28, 2016, 12:44:04 AM6/28/16
to CodenameOne Discussions
One of the reasons we deprecated image download service was the fact that it stores a serialized object rather than the actual image.
So if you name the file using the same name as the ImageDownloadService used URLImage or other API's won't work since they would assume the file has a proper image but will instead get the serialized object from image download service.

Just prefix the names of the files with "urlimg" or something like that to avoid using the existing ImageDownloadService caches.

Bryan Buchanan

unread,
Jun 28, 2016, 12:51:17 AM6/28/16
to CodenameOne Discussions
Each time I ran the code (with one of the 3 types uncommented and the other 2 commented), I did "Clean Storage" in the simulator so I was sure I'd be starting a clean slate for each test.

Shai Almog

unread,
Jun 28, 2016, 12:53:14 AM6/28/16
to CodenameOne Discussions
Notice the stack of the first exception:


    at com.codename1.io.Storage.readObject(Storage.java:256)
    at com.webbtide.tpd.faultcodes.PartsListCellRenderer.getListCellRendererComponent(PartsListCellRenderer.java:88)

I'm guessing your renderer relies on that behavior somewhere...

Bryan Buchanan

unread,
Jun 28, 2016, 1:23:50 AM6/28/16
to CodenameOne Discussions
It does:


        if (Storage.getInstance().exists(part.getUrl())) {
           
EncodedImage myimage = EncodedImage.create((byte[]) Storage.getInstance().readObject(part.getUrl()));
            image
.setIcon(myimage);
       
} else {
            image
.setIcon(blank);
       
}

So if I use URLImage.createToStorage or Util.downloadImageToStorage I shouldn't use Storage.getInstance().readObject(part.getUrl() ?


Shai Almog

unread,
Jun 29, 2016, 1:20:01 AM6/29/16
to CodenameOne Discussions
Generally reading from storage in a renderer or even checking it is probably a bad idea...

I'd remove list usage altogether from most common applications as it no longer has a performance advantage.

Here you are reading the file as a serialized object which worked for the old image download but the new image download is just the image file so reading it to a byte[] and creating the EncodedImage from that would have worked better.

Bryan Buchanan

unread,
Jun 29, 2016, 1:24:36 AM6/29/16
to CodenameOne Discussions

On Wednesday, June 29, 2016 at 3:20:01 PM UTC+10, Shai Almog wrote:
Generally reading from storage in a renderer or even checking it is probably a bad idea...

I'd remove list usage altogether from most common applications as it no longer has a performance advantage.

So just adding a bunch of components to a  BoxLayout_Y parent is the preferred method ?

Bryan Buchanan

unread,
Jun 29, 2016, 1:39:37 AM6/29/16
to CodenameOne Discussions
Further to this, if I add a bunch of components (each one a container with things layed out as per my current cell renderer), what is the equivalent of the List Action event ? Does one of the demo's have this usage pattern ?

Bryan Buchanan

unread,
Jun 29, 2016, 2:25:08 AM6/29/16
to CodenameOne Discussions
Replying to myself - it looks like Lead Component is what is needed.

Shai Almog

unread,
Jun 30, 2016, 12:01:07 AM6/30/16
to CodenameOne Discussions
Yep, also check out the new unleading functionality landing tomorrow: https://www.codenameone.com/blog/unleading-mutating-accordion.html
Reply all
Reply to author
Forward
0 new messages