1

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

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): 在 com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:361) E/AndroidRuntime(16123): 在 android.app.Activity.setContentView(Activity.java:2043) E/AndroidRuntime (16123): 在 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):在 java.lang.reflect.Constructor.constructNative(Native Method) E/AndroidRuntime(16123):在 java.lang.reflect.Constructor.newInstance( Constructor.java:417) E/AndroidRuntime(16123): at 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 Method) 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 更多107) E/AndroidRuntime(16123): 在 android.widget.Button.(Button.java:103) E/AndroidRuntime(16123): ... 28 更多107) E/AndroidRuntime(16123): 在 android.widget.Button.(Button.java:103) E/AndroidRuntime(16123): ... 28 更多

有什么解决办法?

4

3 回答 3

2

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

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

于 2013-05-10T16:02:36.110 回答
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;
    }   
}
于 2013-05-10T15:42:55.700 回答
0

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

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

}

请注意, decodeResource 可能会导致这种情况。我建议您尝试其他方法,因为此功能确实需要大量内存。

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

于 2013-05-10T15:39:47.647 回答