GridView 400 Drawables上的Android java.lang.OutOfMemoryError大小为25Kb

时间:2013-12-20 03:43:53

标签: java android

我很绝望,我不知道该怎么办。我已经尝试了很多东西来解决它,我总是离开OutOfMemory Error。我尝试使用Universal Image Loader库和许多其他网络修复程序,但我总是收到此错误:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:715)
at android.content.res.Resources.loadDrawable(Resources.java:1713)
at android.content.res.Resources.getDrawable(Resources.java:585)
at android.view.View.setBackgroundResource(View.java:7659)
at com.crystalsoftdesign.hearthstone.AdapterImage.getView(AdapterImage.java:153)
at android.widget.AbsListView.obtainView(AbsListView.java:1513)
at android.widget.GridView.makeAndAddView(GridView.java:1226)
at android.widget.GridView.makeRow(GridView.java:272)
at android.widget.GridView.fillDown(GridView.java:225)
at android.widget.GridView.fillGap(GridView.java:192)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:3498)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:2327)
at android.view.View.dispatchTouchEvent(View.java:3934)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:977)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1016)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1125)
at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675)
at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2215)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1899)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
at dalvik.system.NativeStart.main(Native Method)

我的应用程序在GridView中共有393个图像。每个图像都是一个JPG文件,每个文件有25KB。我真的需要帮助,因为现在我完全被阻止而不知道还能做什么。

我把所有的适配器代码都放在这里,看看是否有任何专业人士或了解更多可以帮助我。

public AdapterImage(Context c, ArrayList<BeanCarta> coleccion, int modificarCantidadColumnas, boolean pantallaEditColeccion, Map<Integer, Integer> mapIdsGrid, ArrayList<BeanCarta> mazoVisual){
        try {
            this.mContext = c;
            this.coleccion = coleccion;
            this.modificarCantidadColumnas = modificarCantidadColumnas;
            this.pantallaEditColeccion = pantallaEditColeccion;
            this.mapIdsGrid = mapIdsGrid;
            this.mazoVisual = mazoVisual;
        } catch (Exception e) {
            Utils.logErrorStart(log, "AdapterImage");
            Utils.logErrorIni(this.log, "constructor");
            Utils.appendLog(this.log, e, null);
        }
    }

    public void setAdaptadorParametros(ArrayList<BeanCarta> coleccion, int modificarCantidadColumnas, boolean coleccionPersonal, Map<Integer, Integer> mapIdsGrid){
        this.coleccion = coleccion;
        this.modificarCantidadColumnas = modificarCantidadColumnas;
        this.pantallaEditColeccion = coleccionPersonal;
        this.mapIdsGrid = mapIdsGrid;
    }

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

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

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

    public static class ViewHolder{
        ImageView elemImg;
        LinearLayout elemLayout;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.element_grid, null);

            holder.elemImg = (ImageView) convertView.findViewById(R.id.imagenGrid);
            holder.elemLayout = (LinearLayout) convertView.findViewById(R.id.imagenGridLay);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

            this.carta = this.coleccion.get(position);
            holder.elemImg.setScaleType(ImageView.ScaleType.CENTER_CROP);

            //Detectar si el view del grid, que corresponde a una carta, ya tiene un id asignado.
            //En tal caso se le asigna el mismo id.
            this.id = 0;
            if (this.mapIdsGrid.containsKey(this.carta.getId())){
                this.id = this.mapIdsGrid.get(this.carta.getId());
            }else{
                this.id = Utils.getRandomId(this.mContext);
                this.mapIdsGrid.put(this.carta.getId(), this.id);
            }
            holder.elemImg.setId(this.id);
            holder.elemLayout.setId(this.id);

            //Detectar la trasparencia de la carta si hay cartas disponibles en la colección.
            if (!this.pantallaEditColeccion && this.carta.getCantidad() <= 0){
                holder.elemImg.setVisibility(View.VISIBLE);
            }else{
                holder.elemImg.setVisibility(View.GONE);
            }

            if (!this.pantallaEditColeccion){
                int cantidadMazo = this.mazoVisual.size();
                for (int i = 0; i < cantidadMazo; i++) {
                    if(carta.getId() == this.mazoVisual.get(i).getId()){
                        if(this.mazoVisual.get(i).getCantidad() == Constantes.MAXIMO_COPIAS_MAZO || Constantes.RAREZA_LEGENDARIA.equals(this.mazoVisual.get(i).getRareza())){
                            holder.elemImg.setVisibility(View.VISIBLE);
                            break;
                        }
                    }
                }
            }


            if (this.metrics == null){
                this.metrics = parent.getResources().getDisplayMetrics();
               this.cartaWFinal = (this.metrics.widthPixels / this.modificarCantidadColumnas) - MARGEN_CARTA;
                this.cartaHFinal =  392*this.cartaWFinal/278;
                this.gridView = new GridView.LayoutParams(this.cartaWFinal, this.cartaHFinal);
            }
            holder.elemLayout.setLayoutParams(this.gridView);
            holder.elemLayout.setBackgroundResource(Utils.getIntDrawableByName(this.coleccion.get(position).getImagen(), this.mContext));

        return convertView;
    }

    public DisplayMetrics getMetrics() {
        return metrics;
    }

    public void setMetrics(DisplayMetrics metrics) {
        this.metrics = metrics;
    }

我使用了不同的librearies和differents代码来改进它并且从未解决它。我试图用Eclipe的记忆分析器进行分析,但我无法解决它,因为我不是专业人士而且我不知道如何使用这个工具。

如果您使用解决方案代码发布示例,则可以为我提供更多帮助。或者给我一个带有示例解释的教程,因为我是西班牙人并且不是专业开发人员,很多时候我很难理解人们解释的一些事情。

提前致谢。

2 个答案:

答案 0 :(得分:0)

holder.elemLayout.setBackgroundResource(Utils.getIntDrawableByName(this.coleccion.get(position).getImagen(),this.mContext)); - 这可能是内存不足错误的原因。 您需要将缩小(较小)的图像版本加载到内存中,以将其附加到网格视图中。跟着这些步骤-  首先使用inJustDecodeBounds = true进行解码以检查图像的尺寸

 final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(<your image>, options);//use appropriate parameters for the method.

计算inSampleSize

 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);//reqWidth and reqHeight are width and height of your grid view cell.

计算样本量的方法

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

使用inSampleSize设置

解码图像
 options.inJustDecodeBounds = false;
    Bitmap scaledBitmap =  BitmapFactory.decodeResource(<your image>, options);

最后, 将此scaledBitmap设置为holder.elemLayout的背景。

参考this for more details

答案 1 :(得分:0)

几年后我再次需要它,这个解决方案非常有效!!你好!!