简体   繁体   English

使用setImageURI设置Uri时的OutOfMemoryError

[英]OutOfMemoryError when setting Uri with setImageURI

The user select a image, the path of the image is then stored in my SQLite database. 用户选择一个图像,然后将图像的路径存储在我的SQLite数据库中。 I then populate the text/images from SQLite in a GridView using a CursorAdapter: 然后,我使用CursorAdapter在GridView填充SQLite中的文本/图像:

public class MyNiftyAdapter extends CursorAdapter{
private LayoutInflater mInflater;
private Cursor cur;

public MyNiftyAdapter(Context context, Cursor c) {
    super(context,c);
    this.mInflater = LayoutInflater.from(context);
    this.cur = c;
}
public MyNiftyAdapter(Context context, Cursor c, boolean autoRequery)
{
    super(context, c, autoRequery);
    this.mInflater = LayoutInflater.from(context);
    this.cur = c;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder viewHolder;
    if(convertView == null)
    {
        convertView = this.mInflater.inflate(R.layout.single_item, null);
        viewHolder = new ViewHolder();
        viewHolder.name = (TextView)convertView.findViewById(R.id.txtName);
        viewHolder.Age = (TextView)convertView.findViewById(R.id.studentage);
        viewHolder.Id = (TextView)convertView.findViewById(R.id.rowid);
        viewHolder.Image = (CircularImageView)convertView.findViewById(R.id.imgFood);
        convertView.setTag(viewHolder);
    }else
    {
        viewHolder = (ViewHolder)convertView.getTag();
    }
    this.cur.moveToPosition(position);

    viewHolder.name.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper.NAME)));
    viewHolder.Age.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper.AGE)));
    viewHolder.Id.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper._ID)));
    Uri jg = Uri.parse(this.cur.getString(this.cur.getColumnIndex("imagepath")));
    viewHolder.Image.setImageURI(jg);

    return convertView;
}

@Override
public void bindView(View view, Context context, Cursor cursor) {

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    // Dont need to do anything here
    return null;
}

static class ViewHolder
{
    TextView name;
    TextView Age;
    TextView Id;
    CircularImageView Image;
}
}

When I select large images I get a out of memory error: 当我选择大图像时,我得到一个内存不足错误:

java.lang.OutOfMemoryError: Failed to allocate a 21566748 byte allocation with 8448604 free bytes and 8MB until OOM

I have seen that the bitmap should be scaled down, but I'm just using the Uri of the file and displaying it. 我已经看到位图应该缩小,但我只是使用文件的Uri并显示它。 Is there anyway to avoid this issue as I don't want to save another(compressed) file to the device? 有没有办法避免这个问题,因为我不想将另一个(压缩)文件保存到设备?

I have tried android:hardwareAccelerated="false" in manifest. 我在manifest中尝试过android:hardwareAccelerated="false"


This is what worked for me: 这对我有用:

I ended up using picasso as the answers suggested, but something important to note is that when loading a URI from device is to load the URI like this: 我最后使用picasso作为建议的答案,但需要注意的一点是, 从设备加载URI时要加载这样的URI

Picasso.with(mContext)
            .load(new File(String.valueOf(Uri)))
            .placeholder(R.drawable.profile)
            .resize(800, 800)
            .centerCrop()
            .into(viewHolder.Image);

note that I used .load(new File(String.valueOf(Uri))) instead of .load(uri) . 请注意我使用.load(new File(String.valueOf(Uri)))而不是.load(uri) If you load the URI directly the view will return empty. 如果直接加载URI ,则视图将返回空。

If you load a image from a url , it should be loaded like this: 如果从网址加载图片 ,则应按如下方式加载:

Picasso.with(mContext)
            .load(URL)
            .placeholder(R.drawable.profile)
            .resize(800, 800)
            .centerCrop()
            .into(viewHolder.Image);

So my adapter ended up looking like this: 所以我的适配器最终看起来像这样:

public class MyNiftyAdapter extends CursorAdapter{
private LayoutInflater mInflater;
private Cursor cur;
private Context mContext;

public MyNiftyAdapter(Context context, Cursor c) {
    super(context,c);
    this.mInflater = LayoutInflater.from(context);
    this.mContext = context;
    this.cur = c;
}
public MyNiftyAdapter(Context context, Cursor c, boolean autoRequery)
{
    super(context, c, autoRequery);
    this.mInflater = LayoutInflater.from(context);
    this.cur = c;
    this.mContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder viewHolder;
    if(convertView == null)
    {
        convertView = this.mInflater.inflate(R.layout.single_item, null);
        viewHolder = new ViewHolder();
        viewHolder.name = (TextView)convertView.findViewById(R.id.txtName);
        viewHolder.Age = (TextView)convertView.findViewById(R.id.studentage);
        viewHolder.Id = (TextView)convertView.findViewById(R.id.rowid);
        viewHolder.Image = (CircularImageView)convertView.findViewById(R.id.imgFood);
        convertView.setTag(viewHolder);
    }else
    {
        viewHolder = (ViewHolder)convertView.getTag();
    }
    this.cur.moveToPosition(position);

    viewHolder.name.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper.NAME)));
    viewHolder.Age.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper.AGE)));
    viewHolder.Id.setText(this.cur.getString(this.cur.getColumnIndex(SQLiteHelper._ID)));
    Uri jg = Uri.parse(this.cur.getString(this.cur.getColumnIndex("imagepath")));

    Picasso.with(mContext)
            .load(new File(String.valueOf(jg)))
            .placeholder(R.drawable.profile)
            .resize(800, 800)
            .centerCrop()
            .into(viewHolder.Image);

    return convertView;
}

@Override
public void bindView(View view, Context context, Cursor cursor) {

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    // Dont need to do anything here
    return null;
}

static class ViewHolder
{
    TextView name;
    TextView Age;
    TextView Id;
    CircularImageView Image;
}
}

Thank you all for the help. 谢谢大家的帮助。

You can use Picasso library to display images. 您可以使用Picasso库来显示图像。

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

And in your adapter something like this : 在您的适配器中这样的事情:

Uri jg = Uri.parse(this.cur.getString(this.cur.getColumnIndex("imagepath")));
Picasso.with(context).load(jg).into(viewHolder.Image);

For Context 对于上下文

public class MyNiftyAdapter extends CursorAdapter{
private LayoutInflater mInflater;
private Cursor cur;
private Context mContext;

public MyNiftyAdapter(Context context, Cursor c) {
    super(context,c);
    this.mInflater = LayoutInflater.from(context);
this.mContext= context;
    this.cur = c;
}
public MyNiftyAdapter(Context context, Cursor c, boolean autoRequery)
{
    super(context, c, autoRequery);
    this.mInflater = LayoutInflater.from(context);
    this.cur = c;
    this.mContext= context;

}

an then use : 然后使用:

Uri jg = Uri.parse(this.cur.getString(this.cur.getColumnIndex("imagepath")));
Picasso.with(mContext).load(jg).into(viewHolder.Image);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM