Reputation: 441
In my app I have this error:
E/AndroidRuntime(16123): FATAL EXCEPTION: main
E/AndroidRuntime(16123): java.lang.RuntimeException: Unable to start activity ComponentInfo{it.bisemanuDEV.mathTools/it.bisemanuDEV.mathTools.MainActivity}: android.view.InflateException: Binary XML file line #58: Error inflating class <unknown>
E/AndroidRuntime(16123): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2073)
E/AndroidRuntime(16123): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2098)
E/AndroidRuntime(16123): at android.app.ActivityThread.access$600(ActivityThread.java:138)
E/AndroidRuntime(16123): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1204)
E/AndroidRuntime(16123): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(16123): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(16123): at android.app.ActivityThread.main(ActivityThread.java:4872)
E/AndroidRuntime(16123): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(16123): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(16123): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
E/AndroidRuntime(16123): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
E/AndroidRuntime(16123): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(16123): Caused by: android.view.InflateException: Binary XML file line #58: Error inflating class <unknown>
E/AndroidRuntime(16123): at android.view.LayoutInflater.createView(LayoutInflater.java:613)
E/AndroidRuntime(16123): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
E/AndroidRuntime(16123): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
E/AndroidRuntime(16123): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
E/AndroidRuntime(16123): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
05-11 20:21:56.843: E/AndroidRuntime(16123): at android.view.LayoutInflater.rInflate(LayoutInflater.java:749) E/AndroidRuntime(16123): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) E/AndroidRuntime(16123): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) E/AndroidRuntime(16123): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) E/AndroidRuntime(16123): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:361) E/AndroidRuntime(16123): at android.app.Activity.setContentView(Activity.java:2043) E/AndroidRuntime(16123): at it.bisemanuDEV.mathTools.MainActivity.onCreate(MainActivity.java:27) E/AndroidRuntime(16123): at android.app.Activity.performCreate(Activity.java:5191) E/AndroidRuntime(16123): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1082) E/AndroidRuntime(16123): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2037) E/AndroidRuntime(16123): ... 11 more E/AndroidRuntime(16123): Caused by: java.lang.reflect.InvocationTargetException E/AndroidRuntime(16123): at java.lang.reflect.Constructor.constructNative(Native Method) E/AndroidRuntime(16123): at java.lang.reflect.Constructor.newInstance(Constructor.java:417) E/AndroidRuntime(16123): at android.view.LayoutInflater.createView(LayoutInflater.java:587) E/AndroidRuntime(16123): ... 25 more E/AndroidRuntime(16123): Caused by: java.lang.OutOfMemoryError E/AndroidRuntime(16123): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) E/AndroidRuntime(16123): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500) E/AndroidRuntime(16123): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353) E/AndroidRuntime(16123): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781) E/AndroidRuntime(16123): at android.content.res.Resources.loadDrawable(Resources.java:1969) E/AndroidRuntime(16123): at android.content.res.Resources.getDrawable(Resources.java:673) E/AndroidRuntime(16123): at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173) E/AndroidRuntime(16123): at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:881) E/AndroidRuntime(16123): at android.graphics.drawable.Drawable.createFromXml(Drawable.java:818) E/AndroidRuntime(16123): at android.content.res.Resources.loadDrawable(Resources.java:1954) E/AndroidRuntime(16123): at android.content.res.TypedArray.getDrawable(TypedArray.java:601) E/AndroidRuntime(16123): at android.view.View.(View.java:3347) E/AndroidRuntime(16123): at android.widget.TextView.(TextView.java:494) E/AndroidRuntime(16123): at android.widget.Button.(Button.java:107) E/AndroidRuntime(16123): at android.widget.Button.(Button.java:103) E/AndroidRuntime(16123): ... 28 more
What can be the solution?
Upvotes: 1
Views: 508
Reputation: 5465
The message is pretty self explanatory... You're running out of memory.
Check the parameters that you're passing to this method, there might simply be too many bitmaps being decoded and stored in memory.
Consider caching instead of pre-loading all the bitmaps - only load the bitmap when you actually need to use it. Then add it to a hasmap (from its ID to the actual bitmap). Before decoding a bitmap check if it is already in the map, if it is you don't need to decode it again. Be sure to check the size of the map before decoding new bitmaps, and clear the cache when necessary so you don't run out of memory.
Edit: Here's an example for how you could do it
Edit2: Here's the full class code. Hope I didn't make any typos.
public class CurrencyRateListAdapter extends BaseAdapter {
// This variable is used for debug log (LogCat)
private static final String TAG = "CC:CurrencyRateListAdapter";
private LayoutInflater mInflater;
private String[] mName;
private Integer[] mBitmapIds;
private HashMap<Integer, Bitmap> mBitmaps;
private Context mContext;
private Cursor mRateData;
private double mRate[];
private String mDisplayrate[];
private int mBaseCurrencyPosition;
public CurrencyRateListAdapter(Context context, Integer[] name, Integer[] bitmapID, Cursor rate_data) {
mInflater = LayoutInflater.from(context);
mBitmaps = new HashMap<Integer, Bitmap>();
mBitmapIds = bitmapID;
mContext = context;
mName = new String[name.length];
for(int j=0; j<name.length; j++) {
mName[j] = context.getString(name[j]);
}
mRateData = rate_data;
// update currency rate
updateCurrencyRate();
// set default currency
mBaseCurrencyPosition = 0;
}
@Override
public void finalize() {
Log.d(TAG, "Close SQL cursor...");
mRateData.close();
}
public int getCount() {
return mBitmapIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
//Log.d(TAG, ">>>>> getView: position=" + Integer.toString(position));
try {
if(convertView == null) {
// uses currencyratelist.xml to display each currency selection
convertView = mInflater.inflate(R.layout.currencyratelist, null);
// then create a holder for this view for faster access
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.ratelist_icon);
holder.name = (TextView) convertView.findViewById(R.id.ratelist_text);
holder.rate = (TextView) convertView.findViewById(R.id.ratelist_ratetext);
// store this holder in the list
convertView.setTag(holder);
} else {
// load the holder of this view
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageBitmap(getIcon(mBitmapIds[position]));
holder.name.setText(mName[position]);
holder.rate.setText(mDisplayrate[position]);
} catch (Exception e) {
Log.e(TAG, "getView:" + e.toString());
}
//Log.d(TAG, "<<<<< getView: position=" + Integer.toString(position));
return convertView;
}
public void SetBaseCurrencyIndex(int value) {
mBaseCurrencyPosition = value;
// update display rate
double rate_base = 1.0;
if(mBaseCurrencyPosition < mRate.length) {
rate_base = mRate[mBaseCurrencyPosition];
}
mDisplayrate = new String[mRateData.getCount()];
for(int i=0; i<mRateData.getCount(); i++) {
mDisplayrate[i] = String.format(Locale.US, "%.3f", mRate[i] / rate_base);
}
}
public String getDisplayString(int position) {
String result = "1.000";
if(position < mRate.length) {
result = mDisplayrate[position];
}
return result;
}
public void updateCurrencyRate() {
Log.d(TAG, ">>>>> updateCurrencyRate");
// update currency rate data
mRateData.requery();
mRate = new double[mRateData.getCount()];
int cnt = mRateData.getCount();
int colcnt = mRateData.getColumnCount();
for(int i=0; i<cnt; i++) {
if(mRateData.moveToPosition(i) == true) {
if(colcnt == 1) {
// only currency rate data in the query result set
mRate[i] = mRateData.getDouble(0);
} else {
// all data in the query result set
// So the rate data in the 2nd column (refer to CurrencyConverterDB class
mRate[i] = mRateData.getDouble(1);
}
} else {
mRate[i] = 1.0;
}
}
// deactive currency rate data
mRateData.deactivate();
Log.d(TAG, "<<<<< updateCurrencyRate");
}
public double getCurrencyRate(int position) {
double rate_sel = 1.0;
if(position < mRate.length) {
rate_sel = mRate[position];
}
return rate_sel;
}
/* class ViewHolder */
private class ViewHolder {
ImageView icon;
TextView name;
TextView rate;
}
private Bitmap getIcon(Integer bitmapId) {
Bitmap icon = mBitmaps.get(bitmapId);
if (icon == null) {
icon = BitmapFactory.decodeResource(mContext.getResources(), bitmapId);
mBitmaps.put(bitmapId, icon);
}
return icon;
}
}
Upvotes: 1
Reputation: 2591
Your application memory is growing up too fast... This is how Android manages its memory per application: Lets say when you start your application, it has 10MB of memory. When your application uses for example 8MB, Android predicts that the remaining 2MB may not be sufficient. So Android gives your application some additional memory. So now you have 13MB (for example). This scenario repeats each time Android decides that the remainging memory may not be enough for your application. This way the used memory from the application is growing slowly and Android can manage it more effectively.
In your example you have a loop that is decoding images. This way the size of memory that your application uses grows too fast and Android has no time to gives you more memory.
Upvotes: 2
Reputation: 6867
you are getting java.lang.OutOfMemoryError because you are running this for loop
for(int i=0; i<bitmapID.length; i++) {
mIcon[i] = BitmapFactory.decodeResource(context.getResources(), bitmapID[i].intValue());
}
Note that decodeResource can cause that. I suggest you to try alternative ways as this function really takes lots of memory.
you may also want to calculate the size you need and than decode. in most cases you don't really need the full size.
Upvotes: 0