Question

so Im trying to make an app that when you click on a button, it displays a lot of images. The problem is that when I click the button, the application crashes. Here is a part of my XML file. It has 36 different images:

<ImageView
    android:id="@+id/imageView31"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/veh1" />

    <ImageView
    android:id="@+id/imageView32"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/veh2" />

    <ImageView
    android:id="@+id/imageView33"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/veh3" />

...

And here is the LogCat:

02-18 22:47:00.263: E/AndroidRuntime(366): FATAL EXCEPTION: main
02-18 22:47:00.263: E/AndroidRuntime(366): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.guzi.samphelptools/com.guzi.samphelptools.Vehicles}: android.view.InflateException: Binary XML file line #81: Error inflating class <unknown>
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.os.Looper.loop(Looper.java:130)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread.main(ActivityThread.java:3683)
02-18 22:47:00.263: E/AndroidRuntime(366):  at java.lang.reflect.Method.invokeNative(Native Method)
02-18 22:47:00.263: E/AndroidRuntime(366):  at java.lang.reflect.Method.invoke(Method.java:507)
02-18 22:47:00.263: E/AndroidRuntime(366):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-18 22:47:00.263: E/AndroidRuntime(366):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-18 22:47:00.263: E/AndroidRuntime(366):  at dalvik.system.NativeStart.main(Native Method)
02-18 22:47:00.263: E/AndroidRuntime(366): Caused by: android.view.InflateException: Binary XML file line #81: Error inflating class <unknown>
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.createView(LayoutInflater.java:518)
02-18 22:47:00.263: E/AndroidRuntime(366):  at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:568)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:626)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
02-18 22:47:00.263: E/AndroidRuntime(366):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:207)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.Activity.setContentView(Activity.java:1657)
02-18 22:47:00.263: E/AndroidRuntime(366):  at com.guzi.samphelptools.Vehicles.onCreate(Vehicles.java:14)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
02-18 22:47:00.263: E/AndroidRuntime(366):  ... 11 more
02-18 22:47:00.263: E/AndroidRuntime(366): Caused by: java.lang.reflect.InvocationTargetException
02-18 22:47:00.263: E/AndroidRuntime(366):  at java.lang.reflect.Constructor.constructNative(Native Method)
02-18 22:47:00.263: E/AndroidRuntime(366):  at java.lang.reflect.Constructor.newInstance(Constructor.java:415)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.view.LayoutInflater.createView(LayoutInflater.java:505)
02-18 22:47:00.263: E/AndroidRuntime(366):  ... 24 more
02-18 22:47:00.263: E/AndroidRuntime(366): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.content.res.Res`enter code here`ources.loadDrawable(Resources.java:1709)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.widget.ImageView.<init>(ImageView.java:118)
02-18 22:47:00.263: E/AndroidRuntime(366):  at android.widget.ImageView.<init>(ImageView.java:108)
02-18 22:47:00.263: E/AndroidRuntime(366):  ... 27 more

Okay, so I found this simple listview thing, but i cant get it running.

        import android.os.Bundle;
import android.app.Activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.widget.ListView;
import android.widget.SimpleAdapter;

public class MainActivity extends Activity {

    // Array of integers points to images stored in /res/drawable-hdpi/
    int[] vehs = new int[]{
        R.drawable.veh1,         
        R.drawable.veh2,   
        R.drawable.veh3,
        R.drawable.veh4,
        R.drawable.veh5,
        R.drawable.veh6,
        R.drawable.veh7,
        R.drawable.veh8,
        R.drawable.veh9,
        R.drawable.veh10,
        R.drawable.veh11,         
        R.drawable.veh12,   
        R.drawable.veh13,
        R.drawable.veh14,
        R.drawable.veh15,
        R.drawable.veh16,
        R.drawable.veh17,
        R.drawable.veh18,
        R.drawable.veh19,
        R.drawable.veh20,
        R.drawable.veh21,         
        R.drawable.veh22,   
        R.drawable.veh23,
        R.drawable.veh24,
        R.drawable.veh25,
        R.drawable.veh26,
        R.drawable.veh27,
        R.drawable.veh28,
        R.drawable.veh29,
        R.drawable.veh30,
        R.drawable.veh31,
        R.drawable.veh32,
        R.drawable.veh33,
        R.drawable.veh34,
        R.drawable.veh35,
        R.drawable.veh36,
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Each row in the list stores country name, currency and flag
        List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();

        for(int i=0;i<10;i++){
            HashMap<String, String> hm = new HashMap<String,String>();
            hm.put("", Integer.toString(vehs[i]) );
            aList.add(hm);
        }

        // Keys used in Hashmap
        String[] from = { "flag","txt","cur" };

        // Ids of views in listview_layout
        int[] to = { R.id.vehs};

        // Instantiating an adapter to store each items
        // R.layout.listview_layout defines the layout of each item
        SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), aList, R.layout.listview_layout, from, to);

        // Getting a reference to listview of main.xml layout file
        ListView listView = ( ListView ) findViewById(R.id.listview);

        // Setting the adapter to the listView
        listView.setAdapter(adapter);
    }
}

If you could help me with this, that would be great! :D

Was it helpful?

Solution

The problem you have here is you are loading everything at the same time, I guess. You should try using a ListView and inflate each row! The way this would work is that your app will load an ImageView or two at once and the rest will be left on the side, until the user scrolls close to it.

The tutorial I found for this is (watch #71 to about #87 - you can get all his videos at slidenerd.com):
http://www.youtube.com/watch?v=uic3TVp_j3M#t=0

You should also resize your bitmaps so they aren't loaded in full resolution. You don't need a 1920x1080 image for a 540*420 screen, for example. The following link shows you how to take care of this. http://developer.android.com/training/displaying-bitmaps/index.html

So, in the end, you will have only 1 ListView, 1 ImageView and way less code and way less confusion :P

EDIT: QUICK GUIDE: I'll walk you through the ListView method only, because I think the scaling down of an image example by Google is easy to follow.

So, first of all, you will have the following:

  1. myActivity.xml (the main Activity where you need these images)
  2. Single row (the layout of what a single row looks like)
  3. MyActivity.java (The java class for your activity)

myActivity.xml will contain a ListView:

<ListView
    android:id="@+id/lvList"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true" >
</ListView>

singleRow.xml will contain just an ImageView - you will use the same ImageView's LayoutParamaters and mirror them 36 times:

<ImageView
    android:id="@+id/ivImage"
    android:layout_width="50dp"
    android:layout_height="85dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:src="@drawable/ic_launcher" />

MyActivity.java - where all the magic happens!

public class MyActivity extends Activity implements OnItemClickListener {
    ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        lv = (ListView) findViewById(R.id.lvList);
        MyAdapter adapter = new MyAdapter(this);
        lv.setAdapter(adapter);
        lv.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        MyView holder = (MyView) view.getTag(); // This will get the tag of the item click - that is set up below
    }

    //Create a holder for the image that will be in an ImageView
    class SingleRowData {
        int img;

        SingleRowData(int img) {
            this.img = img;
        }
    }

    //A reference to the ImageView that needs to be copied
    private class MyView {
        ImageView ivImg;

        MyView(View v) {
            ivImg = (ImageView) v.findViewById(R.id.ivHomePageRow);
        }
    }

    class MyAdapter extends BaseAdapter{
        ArrayList<SingleHPSRow> list;
        Context context;

        public MyAdapter(Context context) {
            this.context = context;
            list = new ArrayList<SingleRowData>();
            ...
            int[] imgId = ...; // let's say you are getting all the images from your resources .. you will have to set this up, I'm guessing you know how to.
            for(int item = 0; item < imgUrl.length; i++) {
                list.add(imgId[item]);
            }
        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            view row = convertView; //This will try to see if the row has already been loaded b4
            MyView holder = null; initialize our custome View for the row
            if(row == null) { // new row
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //Get the LayoutInflater
                row = inflater.inflate(R.layout.singleRow, parent, false); //Reference to the row layout
                holder = new MyView(row);
                row.setTag(holder); // Give the row a tag - the holder that contains the item
            } else { // old row
                holder = (MyView) row.getTag(); //Get the tag that was assigned
            }
            SingleRowData item = list.get(position); //Get the item at the current position
            int image = item.img; //Get the imgId assigned to the current item
            holder.ivImg.setImageResource(image); //Load image for the current position
            return row; // Return the current row
        }
    }
}

Hopefull this is well explained, I copied and shortened one of my codes. Let me know if there's something you don't understand

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top