java - 使用 setImageURI 设置 Uri 时出现 OutOfMemoryError

标签 java android sqlite android-memory

用户选择一个图像,图像的路径然后存储在我的 SQLite 数据库中。然后,我使用 CursorAdapter 将 SQLite 中的文本/图像填充到 GridView 中:

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

当我选择大图像时,出现内存不足错误:

java.lang.OutOfMemoryError:无法分配具有 8448604 可用字节和 8MB 的 21566748 字节分配,直到 OOM

我已经看到位图应该缩小,但我只是使用文件的 Uri 并显示它。由于我不想将另一个(压缩的)文件保存到设备中,是否有办法避免此问题?

我已在 list 中尝试过 android:hardwareAccelerated="false"


这对我有用:

我最终使用了picasso正如答案所建议的,但需要注意的是,从设备加载URI是加载URI,如下所示:

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

请注意,我使用了 .load(new File(String.valueOf(Uri))) 而不是 .load(uri)。 如果直接加载URI, View 将返回空。

如果您从网址加载图像,则应按如下方式加载:

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

所以我的适配器最终看起来像这样:

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

谢谢大家的帮助。

最佳答案

您可以使用Picasso库来显示图像。

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

在你的适配器中是这样的:

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

关于java - 使用 setImageURI 设置 Uri 时出现 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46485557/

相关文章:

sqlite - 返回按列分组并由其他列值命名的多行

javascript - sqlite3是否支持从字符串/字节而不是文件加载?

java - 为 Galaxy Gear 制作应用程序

java - 该算法拼图代码(USACO)的良好解决方案?

java - 如何为具有 n :m relationship and multiple primary keys 的 MySQL 数据库表配置实体类

java - 使用 PrettyTime 库格式化时间

java - 为什么我在一个地方得到 "No unique bean is defined",而在另一个地方却没有?

android - React Native Expo Android WebView

android - OnClickListener 只监听第二次

android - 没有主键的sqlite?