我的应用程序中的致命异常

时间:2013-05-10 15:36:29

标签: android android-layout android-intent android-listview

在我的应用中,我有这个错误:

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):在android.view.LayoutInflater.rInflate(LayoutInflater.java:749)     E / AndroidRuntime(16123):在android.view.LayoutInflater.inflate(LayoutInflater.java:489)     E / AndroidRuntime(16123):在android.view.LayoutInflater.inflate(LayoutInflater.java:396)     E / AndroidRuntime(16123):在android.view.LayoutInflater.inflate(LayoutInflater.java:352)     E / AndroidRuntime(16123):at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:361)     E / AndroidRuntime(16123):在android.app.Activity.setContentView(Activity.java:2043)     E / AndroidRuntime(16123):at it.bisemanuDEV.mathTools.MainActivity.onCreate(MainActivity.java:27)     E / AndroidRuntime(16123):在android.app.Activity.performCreate(Activity.java:5191)     E / AndroidRuntime(16123):在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1082)     E / AndroidRuntime(16123):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2037)     E / AndroidRuntime(16123):... 11更多     E / AndroidRuntime(16123):引起: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):在android.view.LayoutInflater.createView(LayoutInflater.java:587)     E / AndroidRuntime(16123):......还有25个     E / AndroidRuntime(16123):引起:java.lang.OutOfMemoryError     E / AndroidRuntime(16123):在android.graphics.BitmapFactory.nativeDecodeAsset(Native方法)     E / AndroidRuntime(16123):在android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500)     E / AndroidRuntime(16123):在android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353)     E / AndroidRuntime(16123):在android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781)     E / AndroidRuntime(16123):在android.content.res.Resources.loadDrawable(Resources.java:1969)     E / AndroidRuntime(16123):在android.content.res.Resources.getDrawable(Resources.java:673)     E / AndroidRuntime(16123):在android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)     E / AndroidRuntime(16123):在android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:881)     E / AndroidRuntime(16123):在android.graphics.drawable.Drawable.createFromXml(Drawable.java:818)     E / AndroidRuntime(16123):在android.content.res.Resources.loadDrawable(Resources.java:1954)     E / AndroidRuntime(16123):在android.content.res.TypedArray.getDrawable(TypedArray.java:601)     E / AndroidRuntime(16123):在android.view.View。(View.java:3347)     E / AndroidRuntime(16123):在android.widget.TextView。(TextView.java:494)     E / AndroidRuntime(16123):在android.widget.Button。(Button.java:107)     E / AndroidRuntime(16123):在android.widget.Button。(Button.java:103)     E / AndroidRuntime(16123):... 28更多

可以解决什么问题?

3 个答案:

答案 0 :(得分:2)

你的应用程序内存增长太快......这就是Android管理每个应用程序的内存的方式:让我们说当你启动你的应用程序时,它有10MB的内存。当您的应用程序使用例如8MB时,Android会预测剩余的2MB可能还不够。因此Android为您的应用程序提供了额外的内存所以现在你有13MB(例如)。每次Android决定重映射内存可能不足以满足您的应用程序时,这种情况会重复出现。这样,来自应用程序的已用内存增长缓慢,Android可以更有效地管理它。

在您的示例中,您有一个解码图像的循环。这样,应用程序使用的内存大小增长得太快,Android没有时间为您提供更多内存。

答案 1 :(得分:1)

这条消息非常自我解释......你的内存已经不足了。

检查您传递给此方法的参数,可能只有太多的位图被解码并存储在内存中。

考虑缓存而不是预加载所有位图 - 只在实际需要使用时加载位图。然后将其添加到hasmap(从其ID到实际位图)。在解码位图之前,检查它是否已经在地图中,如果是,则不需要再次对其进行解码。在解码新位图之前一定要检查地图的大小,并在必要时清除缓存,这样就不会耗尽内存。

编辑:这是一个如何做到这一点的例子

Edit2:这是完整的类代码。希望我没有做任何拼写错误。

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;
    }   
}

答案 2 :(得分:0)

你得到了java.lang.OutOfMemoryError,因为你正在运行这个for循环

for(int i=0; i<bitmapID.length; i++) {
mIcon[i] = BitmapFactory.decodeResource(context.getResources(), bitmapID[i].intValue());

}

请注意,decodeResource可能会导致这种情况。我建议你尝试其他方法,因为这个函数确实需要很多内存。

您可能还想计算所需的尺寸而不是解码。在大多数情况下,你并不需要完整的尺寸。