B4J Question Caching ImageDownloader

Andrew (Digitwell)

Well-Known Member
Licensed User
Longtime User
I'm trying to convert the ImageDownloader class to cache the images locally, in the same way the B4A version does.

I am using the original Imagedownloader class from here : https://www.b4x.com/android/forum/t...internet-link-on-tableview.36506/#post-415621

I added the KeyValueStore from here: https://www.b4x.com/android/forum/threads/keyvaluestore-class.36683/#content

When I make the changes cache from Map to KeyValueStore, in the same way as the B4A version, I get the following error:
B4X:
Error occurred on line: 19 (KeyValueStore)
java.lang.RuntimeException: Cannot serialize object: javafx.scene.image.Image@4d81f2
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.writeType(B4XSerializator.java:258)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.writeObject(B4XSerializator.java:224)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.WriteObject(B4XSerializator.java:104)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.ConvertObjectToBytes(B4XSerializator.java:62)
    at b4j.example.keyvaluestore._put(keyvaluestore.java:264)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:613)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:228)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:159)
    at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:90)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:93)
    at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:480)
    at anywheresoftware.b4a.keywords.Common.access$0(Common.java:460)
    at anywheresoftware.b4a.keywords.Common$CallSubDelayedHelper.run(Common.java:534)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)

It seems to be that the B4X serializator cannot convert the image object.

B4X:
    sql1.ExecNonQuery2("INSERT OR REPLACE INTO main VALUES(?, ?)", Array As Object(Key, ser.ConvertObjectToBytes(Value)))

any idea how to get around this?

Cheers

Andrew
 

Andrew (Digitwell)

Well-Known Member
Licensed User
Longtime User
I think I must have had the wrong version of KeyValueStore.
The version I have has the PutBitmap within #if Not(B4J)

I commented out those lines and changed the WritetoStreamLine and it now works :)

B4X:
'#if not(B4J)
Public Sub PutBitmap(Key As String, Value As Image)
    Dim out As OutputStream
    out.InitializeToBytesArray(0)
   
    'Value.WritetoStream(out,100,"PNG")
    Value.WriteToStream(out)
    Put(Key, out.ToBytesArray)
    out.Close
End Sub

Public Sub GetBitmap(Key As String) As Image
    Dim b() As Byte = Get(Key)
    If b = Null Then Return Null
    Dim in As InputStream
    in.InitializeFromBytesArray(b, 0, b.Length)
    Dim bmp As Image
    bmp.Initialize2(in)
    in.Close
    Return bmp
End Sub
'#End If

I also had to change ImageDownloader

B4X:
Public Sub Download (ImageViewsMap As Map)
    For i = 0 To ImageViewsMap.Size - 1
        tasks.Put(ImageViewsMap.GetKeyAt(i), ImageViewsMap.GetValueAt(i))
        Dim link As String = ImageViewsMap.GetValueAt(i)
        If cache2.ContainsKey(link) Then
            Dim iv As ImageView = ImageViewsMap.GetKeyAt(i)
            iv.PreserveRatio = True
           ' Use GetBitmap instead of Get
            iv.SetImage(cache2.Getbitmap(link))
        Else If ongoingTasks.ContainsKey(link) = False Then
            ongoingTasks.Put(link, "")
            Dim j As HttpJob
            j.Initialize(link, Me)
            j.Download(link)
        End If
    Next
End Sub

Sub JobDone(Job As HttpJob)
    ongoingTasks.Remove(Job.JobName)
    If Job.Success Then
        Dim bmp As Image = Job.GetBitmap
        ' Use Put bitmap instead of Put
        cache2.putBitmap(Job.JobName, bmp)
        If tasks.IsInitialized Then
            For i = 0 To tasks.Size - 1
                Dim link As String = tasks.GetValueAt(i)
                If link = Job.JobName Then
                    Dim iv As ImageView = tasks.GetKeyAt(i)
                    iv.SetImage(bmp)
                End If
            Next
        End If
    Else
        Log("Error downloading image: " & Job.JobName & CRLF & Job.ErrorMessage)
    End If
    If ongoingTasks.Size = 0 Then tasks.Clear
    Job.Release
End Sub
 
Upvote 0
Top