【问题标题】:OutofMemoryError listview sqliteOutofMemoryError listview sqlite
【发布时间】:2015-03-28 23:42:14
【问题描述】:

我在 android 中使用 sqlite,现在我需要填充一个包含 50 多个图像和描述的数据库,在数据库中我保存图像名称,然后我将图像保存在资源中。 问题出在列表视图上,我在其中使用以下代码使用图像。

int resId = getResources().getIdentifier(poiAtual.get_imagemURI(),"drawable",getPackageName());
            holder.foto.setImageResource(resId);

当我快速上下滚动时,应用程序会崩溃并显示内存不足错误。有没有更有效的方法?

谢谢

编辑:这是我的getview

    private class POIListAdapter extends ArrayAdapter<POI> {
    public POIListAdapter() {
        super (Lista.this, R.layout.item_listview, POIs);
    }


    @Override
    public View getView(int position, View view, ViewGroup parent) {
      // lstPOIs.setScrollingCacheEnabled(false);//TODO PARA TESTAR FORMA DE A LISTA NAO TER LAG, usar viewholder
        ViewHolder holder;

        if (view == null) {
            view = getLayoutInflater().inflate(R.layout.item_listview, parent, false);

            holder = new ViewHolder();
            holder.id= (TextView) view.findViewById(R.id.txtID);
            holder.nome = (TextView) view.findViewById(R.id.txtNomePOI);
            holder.descricao = (TextView) view.findViewById(R.id.txtDescricao);
            holder.foto = (ImageView) view.findViewById(R.id.ivFoto);
            view.setTag(holder);

        }
     else {

        holder = (ViewHolder) view.getTag();

        }


        POI poiAtual = POIs.get(position);

        //TextView id=(TextView)view.findViewById(R.id.txtID);
        holder.id.setText(Integer.toString(poiAtual.get_id()));
        //TextView name = (TextView) view.findViewById(R.id.txtNomePOI);
        holder.nome.setText(poiAtual.get_nomePOI());
        //TextView phone = (TextView) view.findViewById(R.id.txtTema);
       // phone.setText(poiAtual.get_tema());
        //TextView descricao = (TextView) view.findViewById(R.id.txtDescricao);
        holder.descricao.setText(poiAtual.get_descricao());
      // ImageView ivFoto = (ImageView) view.findViewById(R.id.ivFoto);
       //ivContactImage.setImageURI(poiAtual.get_imagemURI());


        int resId = getResources().getIdentifier(poiAtual.get_imagemURI(),"drawable",getPackageName());
        holder.foto.setImageResource(resId);
        return view;
    }
}

【问题讨论】:

  • 请贴出你的适配器的getView()方法。
  • 图片有多大?您应该只为列表获取/显示适当大小的图像。 getView() 看起来不错。
  • @BillMote 它们都小于 1mb,我尝试压缩。你是说分辨率??它们介于 800*480 和 1920*1080 之间。我每个图像只有一个尺寸,我应该有 hdpi 和 mhdpi 之类的吗?
  • 拥有适当大小的图像可能会有所帮助,因为任何具有较低 *dpi 的设备几乎肯定具有较高的资源限制。作为快速测试,只需通过 R.drawable.ic_launcher(或 R.mipmap.ic_launcher)进入每个图像并快速滚动。如果您没有遇到 OOM 问题,您将不得不减小图像的大小。延迟加载它们并动态调整大小可以作为解决方案而不是 addint *dpi 图像。
  • @BillMote 与 ic_launcher 的性能要好得多,并且没有崩溃。现在的问题是,当您单击一个列表视图项目时,我需要放置全尺寸的图像。我每个人都必须有2张图片吗?谢谢

标签: java android sqlite android-studio


【解决方案1】:

延迟加载您的图像,根据用例适当调整它们的大小并将它们存储在本地缓存中,这样您就只需要在第一次需要这样做的时候调整大小。

【讨论】:

    【解决方案2】:

    您应该在加载位图时启动here 以获得最佳实践。如果您将非常大的位图加载到图像视图中,您应该将位图缩放到图像视图的边界,这样您就不会浪费不必要的内存。像这样的:

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

    或者您可以使用 Picasso 等图像库来为您处理大部分开销,例如内存缓存、缩放等。

    您还应该注意硬引用可能会阻止图像视图被破坏,从而导致内存泄漏。

    你几乎应该永远使用android:largeHeap="true"。通常这被用作糟糕编程的拐杖。这是来自Android developers page的sn-p:

    但是,请求大堆的能力仅适用于 可以证明需要消耗更多 RAM 的一小部分应用程序(例如 作为大型照片编辑应用程序)。永远不要简单地请求大堆 因为你的内存已经用完了,你需要一个快速修复——你应该 仅当您确切知道所有内存在哪里时才使用它 分配以及为什么必须保留它。然而,即使你很自信 您的应用程序可以证明大堆是合理的,您应该避免要求它 任何可能的程度。使用额外的内存将越来越多 不利于整体用户体验,因为垃圾 收集将花费更长的时间并且系统性能可能会变慢 任务切换或执行其他常见操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多