java.lang.OutOfMemoryError在ListView中

时间:2016-11-07 18:22:30

标签: android listview bitmap out-of-memory android-arrayadapter

我有listView和图像的问题,当设置图像片刻让我成为java.lang.OutOfMemoryError时,这是我在getview中实现的ArrayAdapter

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder viewHolder; // view lookup cache stored in tag
        if(convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.category_list_item, parent, false);
            viewHolder.image = (ImageView) convertView.findViewById(R.id.Icon);
            viewHolder.name = (TextView) convertView.findViewById(R.id.nombreCategoriaTextView);
            viewHolder.name.setText(categories.getCategories(position).getName());
            try {
                DataBaseImageManager manager = new DataBaseImageManager(context);
                Bitmap mIcon11 = manager.getListByName(categories.getCategories(position).getURLImage());
                if (mIcon11 == null)
                    new DownloadImageTask(viewHolder.image, context)
                            .execute(categories.getCategories(position).getURLImage());
                else {
                    (viewHolder.image).setImageBitmap(mIcon11);
                }
            }catch (Exception e){}
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder)convertView.getTag();
        }
        return convertView;
    }

我将我的图像放在sqlIte中并且我从ByteArray中解码位图,实现是下一个

public Bitmap getListByName(String name) {
        Bitmap bmp = null;
        try {
            DataSource.open();
            List<DatosImage> datos = DataSource.obtenerRegistros(name);
            for (DatosImage dato : datos) {
                 bmp = BitmapFactory.decodeByteArray(dato.getValue(), 0, dato.getValue().length);
            }
            DataSource.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bmp;
    }

这可能是我的问题的解决方案或者我的代码是什么?

the error is the nextFATAL EXCEPTION: main
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime: Process: mx.com.sithec.cic, PID: 19660
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime: java.lang.OutOfMemoryError
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:500)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:523)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at mx.com.sithec.cic.ImageHelper.DataBaseImageManager.getListByName(DataBaseImageManager.java:31)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at mx.com.sithec.cic.Adapters.CompanyAdapter.getView(CompanyAdapter.java:102)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.AbsListView.obtainView(AbsListView.java:2283)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.ListView.makeAndAddView(ListView.java:1790)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.ListView.fillUp(ListView.java:725)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.ListView.fillGap(ListView.java:664)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5423)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4534)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.view.Choreographer.doFrame(Choreographer.java:543)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:733)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:136)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5070)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:515)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
11-07 12:31:24.490 19660-19660/? E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:0)

getListByName()中的for循环看起来很奇怪。您可能正在创建多个位图(如果您在一次运行中有许多位图,则可能会导致OutOfMemoryError异常)但只返回一个位图。

你应该做的是:

public Bitmap getListByName(String name) {
    try {
        DataSource.open();
        List<DatosImage> datos = DataSource.obtenerRegistros(name);
        for (DatosImage dato : datos) {
             Bitmap bmp = BitmapFactory.decodeByteArray(dato.getValue(), 0, dato.getValue().length);
             if (bmp != null) {
                 DataSource.close();
                 return bmp;
             }
        }
        DataSource.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

答案 1 :(得分:0)

问题可能实际上是您正在为列表中的每一行创建Bitmap对象。它是内存昂贵的操作,特别是如果位图很大且很多。

我认为解决这个问题的最简单方法是简单地使用已经存在的库中的一个(将图像从URL加载到图像视图)。让我举几个例子

Picasso

非常容易使用,只需将其添加到gour build.gradle

即可

compile 'com.squareup.picasso:picasso:2.5.2'

然后在你的代码中:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

如果您仍想在DB中缓存图像,可以使用Picasso:

Picasso.with(this).load("url").into(new Target()
{
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
    {
        image.setImageBitmap(bitmap);
        //Code for DB save
    }
    @Override
    public void onBitmapFailed(Drawable errorDrawable)
    {
        image.setImageDrawable(errorDrawable);
    }
    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable)
    {
        image.setImageDrawable(placeHolderDrawable);
    }
});

您可能还想查看FrescoGlide