Memory problem with canvas

enemotrop

Member
Licensed User
Longtime User
Hello,

I've a procedure to fill each panel of a scrollview with a gradient of two colors.

This is:

B4X:
Sub InitPanel(pnl As Panel,BorderWidth As Float, FillColor As Int, BorderColor As Int)
   Try
      Dim Rec As Rect
      Dim Canvas1 As Canvas
      Dim BorderWidth_2 As Float
      Dim transicion As GradientDrawable 
      Dim Clrs(3) As Int
      Clrs(0) = Colors.RGB(30,30,30)
      Clrs(1) = FillColor
      Clrs(2) = Colors.RGB(30,30,30)
      transicion.Initialize("TOP_BOTTOM", Clrs)
      BorderWidth_2=BorderWidth/2
      Rec.Initialize(BorderWidth_2,BorderWidth_2,pnl.Width-BorderWidth_2,pnl.Height-BorderWidth_2)
      Canvas1.Initialize(pnl)
      Canvas1.DrawDrawable(transicion, Rec)
      Canvas1.DrawRect(Rec,BorderColor,False,BorderWidth)
      Canvas1.RemoveClip
   Catch
      Log(LastException)
   End Try
End Sub

This code works fine, except when the number of panels in the scrollview is big enough (about 175 panels seems to be the usual limit). The app exits without any exception message, but in the logs I've found:

main_initpanel (B4A line: 147)
Canvas1.Initialize(pnl)
java.lang.OutOfMemoryError: (Heap Size=65571KB, Allocated=63648KB)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:950)
at android.graphics.Bitmap.createBitmap(Bitmap.java:925)
at anywheresoftware.b4a.objects.drawable.CanvasWrapper.Initialize(CanvasWrapper.java:72)
at com.example.main._initpanel(main.java:1566)
at com.example.main._muestrapanel(main.java:1911)
at com.example.main._buscagas(main.java:904)
at com.example.main._wifi1_foundlocation(main.java:2254)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:167)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:151)
at com.AB.ABWifi.ABWifi$2.onLocationChanged(ABWifi.java:396)
at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:260)
at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:193)
at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:209)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:155)
at android.app.ActivityThread.main(ActivityThread.java:5485)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:795)
at dalvik.system.NativeStart.main(Native Method)
** Activity (main) Resume **

It seems that the problem is due to the big number of canvas that are being initialized.

I need to display panels with several gradients, so I can't use the same gradient for all the panels.

Is there a way to 'unload' each canvas rectangle after it's painted? Does it remain visible into its panel? Can I draw only that canvas that are actually visible into the scrollview in a specific time?

Thanks
 

enemotrop

Member
Licensed User
Longtime User
Hello again.

I've got a workaround. This code is put in the main sub, instead of invoking InitPanel:

B4X:
Dim transicion As GradientDrawable 
Dim Clrs(3) As Int
If doppler >=0 Then
  Clrs(1) = Colors.RGB(30,30,30 + doppler)
Else
  Clrs(1) = Colors.RGB(30 - doppler,30,30)
End If
Clrs(0) = Colors.RGB(20,20,20)
Clrs(2) = Colors.RGB(20,20,20)
transicion.Initialize("TOP_BOTTOM", Clrs)
pnltest.Background = transicion

It draws the gradient without the use of any canvas or drawing rectangles... which was useful to paint a border on each panel. So this is a provisional solution, but I'm still intrigued about how to deal with several canvas...

Thanks
 
Last edited:
Upvote 0
Top