Android Question How to appication stable

fishwolf

Well-Known Member
Licensed User
Longtime User
i have finish a big application, but work fine only for few minuts, it crash for out of memory.

i have read many threads on forum but i don't resolve.

FIRST PROBLEM
with monitor utility i have indentify the first section and problem of memory leak
i have a list of strings and use a canvas object and MeasureStringWidth for truncate the long strings
when i change the orientation of phone i lost about 2 Mb with the only initialization of canvas object

what is the right method for destroy canvas object ?

B4X:
// Create List
CanvasText.Initialize(Activity)
   
   For i = 0 To ValuesItems.Size - 1
     
     // if don't run the function the memory leak is already present
     Label1.Text = TrimWidth(CanvasText, Label1.Text, Label1.Typeface, Label1.TextSize, LabelWidth)
  
  Next

Sub TrimWidth(CanvasText As Canvas, Text As String, Style As Typeface, Size As Int, MaxWidth As Int) As String
Dim Width As Int
   
   
   If Style.IsInitialized = False Then
       Style = Typeface.DEFAULT
   End If
   
   Width = CanvasText.MeasureStringWidth(Text, Style, Size)
   If Width >= MaxWidth Then
     Do Until Width < MaxWidth
       Text = Text.SubString2(0, Text.Length - 1)
       Width = CanvasText.MeasureStringWidth(Text, Style, Size)
     Loop
     Text = Text.SubString2(0, Text.Length - 3) & "..."
     Return Text
   Else
     Return Text
   End If
   
End Sub
 

klaus

Expert
Licensed User
Longtime User
Instead of
B4X:
CanvasText.Initialize(Activity)
use:
B4X:
Private bmp As Bitmap
bmp.InitializeMutable(2dip, 2dip)   
CanvasText.Initialize2(bmp)
This will reduce memory consumption.
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
Instead of
B4X:
CanvasText.Initialize(Activity)
use:
B4X:
Private bmp As Bitmap
bmp.InitializeMutable(2dip, 2dip)  
CanvasText.Initialize2(bmp)
This will reduce memory consumption.

ok, now work better, now each change orientation consumption about 100Kb

is it possible have zero consumption ?
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
SECOND PROBLEM
Into a listview similar to http://www.b4x.com/android/forum/threads/another-scrollview-example.8417/#post47107

i have differenet images into the list
i think that the 2 images or ImageView consumption about 300Kb for each change orientation

what it the right method ?
thanks

B4X:
Type TypeRows( _
  ID As Int, _
  Pages As Int, _
  MyImage As ImageView)
Dim TabRowss(50) As TypeRows

Bitmap1.Initialize(File.DirAssets,"1.png")
Bitmap2.Initialize(File.DirAssets,"2.png")

For i = 0 To ValuesItems.Size - 1

     TabRows(i).ImageRow.Initialize("View")
     TabRows(i).ImageRow.Tag = i
     Panel1.AddView(TabRows(i).ImageRow,5dip,5dip,65dip,90dip)
 
     If ValueMap.Get("type") == "1" Then
       TabRows(i).ImageRow.Bitmap=Bitmap1
     End If
     If ValueMap.Get("type") == "2" Then
       TabRows(i).ImageRow.Bitmap=Bitmap2
     End If
     TabRows(i).ImageRow.Gravity = Gravity.FILL

next
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
130 * 180 * 4 = 93600
That's about 94 kB per bitmap

You might consider :
B4X:
Bitmap1.InitializeSample(File.DirAssets,"1.png", 65dip, 180dip)
Bitmap2.InitializeSample(File.DirAssets,"2.png", 65dip, 180dip)
Not sure if it will solve your problem.
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
Can you upload your project (File - Export as zip)?

this is the project with only the listview with 2 images,

i wanted to be sure that other features do not impact on the behavior

each change rotation the memory heap is in incremented of 300-500 Kb
 

Attachments

  • MemoryLeak.zip
    130.3 KB · Views: 258
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
Do you eventually get an out of memory exception? Can you post the stack trace?
B4X:
Downsampling image due to lack of memory.

java.lang.OutOfMemoryError

   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:514)
   at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.InitializeSample(CanvasWrapper.java:535)
   at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:512)
   at memory.leak.calendar._findlocandina(calendar.java:563)
   at memory.leak.calendar._seteventslist(calendar.java:1037)
   at memory.leak.calendar._activity_create(calendar.java:371)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
   at memory.leak.calendar.afterFirstLayout(calendar.java:98)
   at memory.leak.calendar.access$100(calendar.java:16)
   at memory.leak.calendar$WaitForLayout.run(calendar.java:76)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4745)
   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:786)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
   at dalvik.system.NativeStart.main(Native Method)
OR
B4X:
Downsampling image due to lack of memory.
Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4
Downsampling image due to lack of memory.
Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4

java.lang.OutOfMemoryError
   at android.os.Parcel.nativeReadString(Native Method)
   at android.os.Parcel.readString(Parcel.java:1473)
   at bwe.n(SourceFile:204)
   at aex.a(SourceFile:83)
   at afa.a(SourceFile:104)
   at aer.a(SourceFile:174)
   at aer.a(SourceFile:151)
   at afw.run(SourceFile:14)
   at afy.run(SourceFile:30)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
   at java.lang.Thread.run(Thread.java:856)
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
I don't see any sub named findlocandina in the code you posted.
where ? i don't find it

anywhere it'was a function for a next step that download and replace the image of listview

you can ingnored, the problem is in firsdt step, into list view with default images
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The error happens inside this method:
B4X:
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:514)
 at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.InitializeSample(CanvasWrapper.java:535)
 at anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper.Initialize(CanvasWrapper.java:512)
 at memory.leak.calendar._findlocandina(calendar.java:563) <-------------------
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
Sorry, sorry,
I did a bit of confusion with projects, post a new project, error and sheenshot of memory on start and before the error

B4X:
** Activity (calendar) Pause, UserClosed = false **
** Activity (calendar) Create, isFirst = false **
Downsampling image due to lack of memory.
java.lang.OutOfMemoryError
   at android.os.Parcel.nativeReadString(Native Method)
   at android.os.Parcel.readString(Parcel.java:1473)
   at bwe.n(SourceFile:204)
   at aex.a(SourceFile:83)
   at afa.a(SourceFile:104)
   at aer.a(SourceFile:174)
   at aer.a(SourceFile:151)
   at afw.run(SourceFile:14)
   at afy.run(SourceFile:30)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
   at java.lang.Thread.run(Thread.java:856)

Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4
Downsampling image due to lack of memory.
Downsampling image due to lack of memory: 2
Downsampling image due to lack of memory: 4

Size Calendar.json=0
java.lang.OutOfMemoryError
  at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
   at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
   at java.lang.StringBuilder.append(StringBuilder.java:216)
   at anywheresoftware.b4a.objects.streams.File$TextReaderWrapper.ReadAll(File.java:588)
   at anywheresoftware.b4a.objects.streams.File.GetText(File.java:221)
   at memory.leak.calendar._seteventslist(calendar.java:620)
   at memory.leak.calendar._activity_create(calendar.java:352)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
   at memory.leak.calendar.afterFirstLayout(calendar.java:98)
   at memory.leak.calendar.access$100(calendar.java:16)
   at memory.leak.calendar$WaitForLayout.run(calendar.java:76)
   at android.os.Handler.handleCallback(Handler.java:615)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:4745)
   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:786)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
   at dalvik.system.NativeStart.main(Native Method)
 

Attachments

  • MemoryLeak.zip
    130.4 KB · Views: 234
  • Memory.jpg
    Memory.jpg
    51.7 KB · Views: 217
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
I wasn't able to reproduce it. I changed the orientation many times to recreate the calendar activity.

Which device are you testing it on?

Galaxy Nexus and Nexus S

you must change orientation into calendar activity, click into "Calendar" button

fo each change orientation the memory heap is incremented about 300-500 Kb, for a crash you must done many change
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Devices running Android versions prior to Android 3.0 are slower to release bitmaps memory. You can use Bitmap.Recycle (with Reflection library) to force the bitmap to release the memory.

A better solution is to load the bitmaps once and store then in a process global list or map and then avoid loading them again and again.
 
Upvote 0

fishwolf

Well-Known Member
Licensed User
Longtime User
for both devices i have version 4.

i moved the bitmap and loading on main activity (one time) and use bitmap from calendar activity (many times the same objects)

i have removed also the canvas object.

but the memory leak is always present.

i know that for this case the memory leak is low, but for others applications with more images with major dimension the problem leads to crash soon.

each one crash ,one user lost :)
 

Attachments

  • MemoryLeak.zip
    130.5 KB · Views: 243
Last edited:
Upvote 0
Top