1

for my little game i use a lot of Image Buttons! The problem is that the application is lagging on some mobiles..but i dont find the problem.

Here is a Screenshot that you can imagine it better:

enter image description here

Now the question is how I got it running smoothly ? Pls i need our help :) Here is the menu xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="de.unikatproduktion.smaragdhunter.MenueActivity"
android:background="@drawable/menuehintergrund">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageButton
        android:layout_width="90dp"
        android:layout_height="45dp"
        android:id="@+id/btn_zurvollversion"
        android:scaleType="fitXY"
        android:background="@drawable/btnzurvollversion"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp" />

    <ImageView
        android:background="@drawable/smaragdmenueanim"
        android:id="@+id/imgshhg"
        android:scaleType="fitXY"
        android:layout_width="250dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="110dp" />

    <ImageButton
        android:layout_width="90dp"
        android:layout_height="45dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:id="@+id/btnmusikanaus"
        android:scaleType="fitXY"
        android:background="@drawable/buttonmusikanausnewclickeddddd"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="275dp"
        android:layout_marginRight="15dp"
        android:layout_gravity="right" />

    <ImageView
        android:id="@+id/zauberermenue"
        android:scaleType="fitXY"
        android:background="@drawable/zauberermenuehgg"
        android:layout_height="60dp"
        android:layout_above="@+id/btn_highscore"
        android:layout_toRightOf="@+id/btn_appbewerten"
        android:layout_toEndOf="@+id/btn_appbewerten"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="221dp"
        android:layout_width="60dp" />

    <ImageButton
        android:id="@+id/btn_appbewerten"
        android:scaleType="fitXY"
        android:background="@drawable/btnappbewerten"
        android:layout_width="90dp"
        android:layout_height="45dp"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="15dp" />

    <ImageButton
        android:id="@+id/btn_start"
        android:scaleType="fitXY"
        android:background="@drawable/btnstart"
        android:layout_height="90dp"
        android:layout_alignParentBottom="true"
        android:layout_alignLeft="@+id/btn_highscore"
        android:layout_alignStart="@+id/btn_highscore"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_marginTop="375dp"
        android:layout_gravity="center_horizontal"
        android:layout_width="220dp" />

    <Spinner
        android:layout_width="220dp"
        android:layout_height="90dp"
        android:id="@+id/schwierigkeitsgrad"
        android:background="@drawable/btnschwierigkeit"
        android:layout_marginTop="280dp"
        android:scrollbarSize="100dp"
        android:foregroundGravity="center"
        style="@style/Widget.AppCompat.Spinner"
        android:animationCache="false"
        android:animateLayoutChanges="false"
        android:alwaysDrawnWithCache="false"
        android:clipChildren="false"
        android:elevation="0dp"
        android:layout_gravity="center_horizontal"
        android:dropDownSelector="@android:drawable/list_selector_background"
        android:popupElevation="@dimen/activity_horizontal_margin"
        android:spinnerMode="dropdown" />

    <TextView
        android:text="Die Vollversion bietet ein besseres Spielerlebnis!"
        android:singleLine="true"
        android:scrollHorizontally="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:textColor="#000000"
        android:textStyle="bold"
        android:id="@+id/werbeview"
        android:textSize="20sp"
        android:layout_marginLeft="4dp"
        android:layout_gravity="bottom|center"
        android:layout_marginBottom="7dp" />

    <ImageButton
        android:layout_width="90dp"
        android:layout_height="45dp"
        android:background="@drawable/btnenglisch"
        android:id="@+id/sprache"
        android:scaleType="fitXY"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="60dp" />

    <ImageButton
        android:id="@+id/insta"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="60dp"
        android:layout_marginTop="220dp"
        android:background="#00000000"
        android:scaleType="fitXY"
        app:srcCompat="@drawable/instaiconklein" />
</FrameLayout>

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
jordy
  • 51
  • 5

3 Answers3

4

It usually happens when the images have high resolutions. It could be the case that you have one ImageView in the whole app that could make the app crash as the device faces an overhead trying to render it.

Omar El Halabi
  • 2,118
  • 1
  • 18
  • 26
  • And how can I adjust the resolution of the images on the different mobile phones? – jordy Apr 04 '17 at 20:17
  • You can do it using [9-patch-resizer](https://github.com/redwarp/9-patch-resizer) tool, which takes a large resolution image and generate same images with lower resolutions for different screen densities. Therefore, you can put the generated images in the `res` folder of your project and the app will use the appropriate image at runtime. – Omar El Halabi Apr 04 '17 at 21:51
2

Try to reuse your bitmaps , so it doesn't have to be decoded every time the user opens your game. You can use InBitmap in BitmapFactory.Optionslike in this code :

public class ImageCache {

Set<SoftReference<Bitmap>> mReusableBitmaps;

protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
    Bitmap bitmap = null;

    if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
        synchronized (mReusableBitmaps) {
            final Iterator<SoftReference<Bitmap>> iterator
                    = mReusableBitmaps.iterator();
            Bitmap item;

            while (iterator.hasNext()) {
                item = iterator.next().get();

                if (null != item && item.isMutable()) {
                    // Check to see it the item can be used for inBitmap.
                    if (canUseForInBitmap(item, options)) {
                        bitmap = item;

                        // Remove from reusable set so it can't be used again.
                        iterator.remove();
                        break;
                    }
                } else {
                    // Remove from the set if the reference has been cleared.
                    iterator.remove();
                }
            }
        }
    }
    return bitmap;
}

int getBytesPerPixel(Bitmap.Config config) {
    if (config == Bitmap.Config.ARGB_8888) {
        return 4;
    } else if (config == Bitmap.Config.RGB_565) {
        return 2;
    } else if (config == Bitmap.Config.ARGB_4444) {
        return 2;
    } else if (config == Bitmap.Config.ALPHA_8) {
        return 1;
    }
    return 1;
}
public boolean canUseForInBitmap(Bitmap candidate, BitmapFactory.Options targetOptions) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // From Android 4.4 (KitKat) onward we can re-use if the byte size of
        // the new bitmap is smaller than the reusable bitmap candidate
        // allocation byte count.
        int width = targetOptions.outWidth / targetOptions.inSampleSize;
        int height = targetOptions.outHeight / targetOptions.inSampleSize;
        int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
        return byteCount <= candidate.getAllocationByteCount();
    }

    // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
    return candidate.getWidth() == targetOptions.outWidth
            && candidate.getHeight() == targetOptions.outHeight
            && targetOptions.inSampleSize == 1;
}

public void addInBitmapOptions(BitmapFactory.Options options) {
    // inBitmap only works with mutable bitmaps, so force the decoder to
    // return mutable bitmaps.
    options.inMutable = true;

    if (this != null) {
        // Try to find a bitmap to use for inBitmap.
        Bitmap inBitmap = getBitmapFromReusableSet(options);

        if (inBitmap != null) {
            // If a suitable bitmap has been found, set it as the value of
            // inBitmap.
            options.inBitmap = inBitmap;
        }
    }
}
public Bitmap decodeSampledBitmapFromFile(Resources res,int id) {

    final BitmapFactory.Options options = new BitmapFactory.Options();

    BitmapFactory.decodeResource(res, id , options);

    // If we're running on Honeycomb or newer, try to use inBitmap.
    addInBitmapOptions(options);

    return BitmapFactory.decodeResource(res, id ,options);
}

I hope this works for you :) , and if not you can check this answer

Community
  • 1
  • 1
  • okay thank you! :) I just need to create a new class and paste this code? – jordy Apr 04 '17 at 20:54
  • ya , something like this : `bitmap = new ImageCache.decodeSampledBitmapFromFile(getResources , R.drawable.your_img);` – Hesham Haikal Apr 04 '17 at 20:59
  • puhhh okay i am a beginner i will try it..if I can not do it can you help me maybe? i can send you all my stuff – jordy Apr 04 '17 at 21:04
  • Sure , But First do you understand what does this code do ? Second , you don't need to send me your stuff :) – Hesham Haikal Apr 04 '17 at 21:10
  • You can explain again what the code does exactly if it's okay.. And what must I exactly in the code change – jordy Apr 04 '17 at 21:13
  • Okay , what happens is: It checks if this bitmap was decoded before or not by checking in caches , if there is , load it using `InBitmap` otherwise decode the bitmap. sounds good ? now try it and compare the difference in performance if you still have the lagging , check the link in my answer. – Hesham Haikal Apr 04 '17 at 21:20
  • Oh I forgot to add something , add this to your Manifest in Application section : `android:largeHeap="true"` maybe that will help – Hesham Haikal Apr 04 '17 at 21:22
  • okay thanks :) And in which place in the class I must declare my pictures? – jordy Apr 04 '17 at 21:27
  • The `ImageCache` class should have a file for itself , so what you have to do is just call the method `decodeSampledBitmapFromFile` like this : `ImageCache ic = new ImageCache(); Bitmap yourPic = ic.decodeSampledBitmapFromFile(getResources , R.drawable.your_pic);` – Hesham Haikal Apr 04 '17 at 21:30
  • Yes but in which class at which place should I call this line – jordy Apr 04 '17 at 21:40
  • The class you are using to set Bitmap of your image buttons – Hesham Haikal Apr 04 '17 at 21:43
  • ImageButton insta = (ImageButton) this.findViewById(R.id.insta); Bitmap bitmap = new ImageCache().decodeSampledBitmapFromFile(getResources(), R.drawable.instaiconklein); insta.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (leseSound()==0 || leseSound()==1) { btnbuttonsound.start(); vibe.vibrate(20); menuemusik.stop(); like this? – jordy Apr 04 '17 at 22:00
  • you forgot to add this : `insta.setImageBitmap(bitmap);` – Hesham Haikal Apr 04 '17 at 22:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139910/discussion-between-hesham-haikal-and-jordy). – Hesham Haikal Apr 04 '17 at 22:11
  • Android Studio doesnt find setImageBitmap – jordy Apr 04 '17 at 22:14
0

You can turn on 'Profile GPU rendering' in Settings/Developer options to see whether it is the rendering at all, that makes your app lag.

Ridcully
  • 23,362
  • 7
  • 71
  • 86