-1

I need to design a screen with over 50 buttons. I can not create the buttons programmatically and should put them one by one into the XML layout manually since the sizes and positions of buttons are not regular. However, I designed XML layout with over 50 buttons and could inflate it successfully in the activity.

When I build the project, it looks like working smoothly but I can see this in the log.

I/Choreographer: Skipped 56 frames! The application may be doing too much work on its main thread.

Is there any good idea that can build the layout without this problem?

To clarify, I attached a screenshot that shows how the UI will look like. As you can see, I need every leaves to be clickable and I should change their colors. enter image description here

And sometimes it crashes when reloading this activity in the app. Here is the crash log.

FATAL EXCEPTION: main Process: com.au.therefreshproject.refreshandgogreen, PID: 14151 java.lang.OutOfMemoryError: Failed to allocate a 301476 byte allocation with 77600 free bytes and 75KB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080) at android.content.res.Resources.loadDrawableForCookie(Resources.java:2635) at android.content.res.Resources.loadDrawable(Resources.java:2540) at android.content.res.TypedArray.getDrawable(TypedArray.java:870) at android.graphics.drawable.StateListDrawable.inflateChildElements(StateListDrawable.java:170) at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:115) at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:1215) at android.graphics.drawable.Drawable.createFromXml(Drawable.java:1124) at android.content.res.Resources.loadDrawableForCookie(Resources.java:2630) at android.content.res.Resources.loadDrawable(Resources.java:2540) at android.content.res.TypedArray.getDrawable(TypedArray.java:870) at android.view.View.(View.java:3948) at android.widget.TextView.(TextView.java:677) at android.widget.Button.(Button.java:109) at android.widget.Button.(Button.java:105) at android.support.v7.widget.AppCompatButton.(AppCompatButton.java:62) at android.support.v7.widget.AppCompatButton.(AppCompatButton.java:58) at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:109) at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:1008) at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1067) at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:189) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:746) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.inflate(LayoutInflater.java:515) at android.view.LayoutInflater.inflate(LayoutInflater.java:423)

Some parts of XML layout are here.

<RelativeLayout
                android:layout_width="320dp"
                android:layout_height="400dp"
                android:layout_centerHorizontal="true"
                android:layout_alignParentBottom="true">
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/tree_01"
                    android:layout_alignParentBottom="true"/>
                <Button
                    android:id="@+id/treenBtn0"
                    android:layout_width="19dp"
                    android:layout_height="31dp"
                    android:layout_marginLeft="31dp"
                    android:layout_marginTop="90dp"
                    android:tag="28"
                    android:background="@drawable/tree_02"/>
                <Button
                    android:id="@+id/treenBtn1"
                    android:layout_width="27dp"
                    android:layout_height="22dp"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="122dp"
                    android:tag="29"
                    android:background="@drawable/tree_03"/>

And the drawable resource is

drawable/tree_02.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/tree_02_on"/>
    <item android:drawable="@drawable/tree_02_off"/>
</selector>
drawable/tree_03.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/tree_03_on"/>
    <item android:drawable="@drawable/tree_03_off"/>
</selector>
nine9stars
  • 239
  • 2
  • 11
  • That's obviously not the best approach to go ahead with. Can you share a sketch or a screenshot of how you want the UI to look? – Joel Fernandes Aug 26 '16 at 18:00
  • sure, I will attach a screenshot shortly. – nine9stars Aug 26 '16 at 18:02
  • Best way will be to use Recycler view with View Types. Out of 50 there will be at least some have same type of layouts. According to conditions we can change the view type. – Akshay Shinde Aug 26 '16 at 18:04
  • please check the screenshot attached. – nine9stars Aug 26 '16 at 18:12
  • @AkshayShinde how recycler view is useful with this layout type? – Marcin Orlowski Aug 26 '16 at 18:15
  • Ahh! This screenshot was not here b4.! – Akshay Shinde Aug 26 '16 at 18:16
  • @AkshayShindeyou can not see the screenshot? – nine9stars Aug 26 '16 at 18:19
  • @JoelFernandes do you have a good idea? – nine9stars Aug 26 '16 at 18:35
  • Looks like a good candidate for a custom View. – Michael Krause Aug 26 '16 at 18:36
  • @star99 oh wow! Okay, the best way to go about is by creating a custom view for this. Designing this in XML is not advisable. – Joel Fernandes Aug 26 '16 at 18:38
  • The reason I mentioned a custom View is because you've got many arbitrarily positioned, sized, and rotated buttons (leafs). Writing this as a single custom View is a bit harder, but will be much more efficient. If you did all of the canvas drawing yourself, you wouldn't need any sub-views. You would need to catch touch events and do some math to route to the leaf that was touched. – Michael Krause Aug 26 '16 at 18:43
  • As an aside - the stack trace you provided indicates that you're loading a pretty big drawable for your leaf buttons and running out of memory. You'll want to ensure that the drawable image is a reasonable size and bit depth. – Michael Krause Aug 26 '16 at 18:45
  • could you guys explain me more in detail about the custom view? now I just put 50 buttons with the background of leaf image in the xml layout. I would be appreciated it if you guys could post a sample code – nine9stars Aug 26 '16 at 18:46
  • Google "android custom views". The "Creating Custom Views" tutorial from the Android developer site is the first item to come up. It's a great place to start. – Michael Krause Aug 26 '16 at 18:48
  • so the custom view should be extended from Button or View? – nine9stars Aug 26 '16 at 18:52

2 Answers2

0

Due to lacking code I cannot answer as well with code. So here are some tips on preventing crashes.

  • Call finish on activities you no longer need

YOu said the problem occurs when restarting the app. I have also gotten the "App skipped [x] frames! The application may be doing too much work on it's main thread."

  • Adding a thread to control actions that the system does not need to control
  • Remember to propperly shut down your activity; Stop actions that does not need to run in the background. Maybe make it impossible to restart into the activity
  • Wipe all arraylists, lists, [] arrays and all things that may take too much memory
Zoe
  • 23,712
  • 16
  • 99
  • 132
-1

OutOfMemoryError is a common problem when you are working with Bitmap. Try enabling largeHeap in manifest file. use android:largeHeap="true" inside application tag in manifest file. Check this solution.

Community
  • 1
  • 1
Abu Yousuf
  • 4,421
  • 2
  • 23
  • 39
  • @star99 it might have been easier if you had added the xml file and the manifest and build.gradle to avoid answers of what you have already done – Zoe Aug 26 '16 at 19:24
  • Try releasing the allocated memory by bitmap and views in onDestroy() method. – Abu Yousuf Aug 26 '16 at 19:27