SQLite Blob没有转换为字符串错误

时间:2017-12-20 15:29:51

标签: android sqlite

这篇文章是我之前关于将图像保存到SQLite的问题的延续。我得到无法在FoodList活动启动时将Blob转换为String错误。我正在使用SQLite Helper和适配器。我的主要活动代码如下:

public static SQLiteHelper sqLiteHelper;

final int REQUEST_CODE_GALLERY = 999;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    init();

    sqLiteHelper = new SQLiteHelper(this, "FoodDB.sqlite", null, 1);

    sqLiteHelper.queryData("CREATE TABLE IF NOT EXISTS FOOD (name TEXT, price TEXT, image BLOB)");

    btnChoose.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ActivityCompat.requestPermissions(
                    MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    REQUEST_CODE_GALLERY
            );
        }
    });

    btnAdd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            try {
                sqLiteHelper.insertData(
                        edtName.getText().toString().trim(),
                        edtPrice.getText().toString().trim(),
                        imageViewToByte(imageView)

                );
                Toast.makeText(getApplicationContext(), "Entry Added", Toast.LENGTH_LONG).show();
                edtName.setText("");
                edtPrice.setText("");
                imageView.setImageResource(R.mipmap.ic_launcher);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    });
    btnList.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, FoodList.class);
            startActivity(intent);
        }
    });
}

private byte[] imageViewToByte(ImageView image) {
    Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] byteArray = stream.toByteArray();
    return byteArray;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(requestCode == REQUEST_CODE_GALLERY) {
        if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            startActivityForResult(intent, REQUEST_CODE_GALLERY);
        }
        else {
            Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_LONG).show();
        }
        //return;
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode == REQUEST_CODE_GALLERY && resultCode == RESULT_OK && data != null) {
        Uri uri = data.getData();
        try {
            InputStream inputStream = getContentResolver().openInputStream(uri);

            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            imageView.setImageBitmap(bitmap);
        }
        catch (FileNotFoundException e){
            e.printStackTrace();
        }

    }

    super.onActivityResult(requestCode, resultCode, data);

}

private void init() {
     edtName = findViewById(R.id.edtName);
     edtPrice = findViewById(R.id.edtPrice);
     btnChoose = findViewById(R.id.btnChoose);
     btnAdd = findViewById(R.id.btnAdd);
     btnList = findViewById(R.id.btnList);
     imageView = findViewById(R.id.imageView);

}

}

然后我的SQLite Helper类如下:

public class SQLiteHelper extends SQLiteOpenHelper {

public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, name, factory, version);


}
public void queryData(String sql) {
    SQLiteDatabase database = getWritableDatabase();
    database.execSQL(sql);
}

public void insertData(String name, String price, byte[] image) {
    SQLiteDatabase database = getWritableDatabase();
    String sql = "INSERT INTO FOOD VALUES (?, ?, ?)";

    SQLiteStatement statement = database.compileStatement(sql);
    statement.clearBindings();

    statement.bindString(1, name);
    statement.bindString(2, price); 
    statement.bindBlob(3, image);

    statement.executeInsert();
}
public Cursor getData(String sql) {
    SQLiteDatabase database = getReadableDatabase();
    return database.rawQuery(sql, null);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {

}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

}

}

我的食物清单适配器代码是:

public class FoodListAdapter extends BaseAdapter {

private Context context;
private int layout;
private ArrayList<Food> foodsList;

public FoodListAdapter(Context context, int layout, ArrayList<Food> foodsList) {
    this.context = context;
    this.layout = layout;
    this.foodsList = foodsList;
}

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

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

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

private class ViewHolder {

    ImageView imageView;
    TextView txtName, txtPrice;
}

@Override
public View getView(int position, View view, ViewGroup viewGroup) {

    View row = view;
    ViewHolder holder = new ViewHolder();
    if(row == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(layout, null);

        holder.txtName = (TextView) row.findViewById(R.id.txtName);
        holder.txtPrice = (TextView) row.findViewById(R.id.txtPrice);
        holder.imageView = (ImageView) row.findViewById(R.id.imgFood);
        row.setTag(holder);

    }
    else  {
        holder = (ViewHolder) row.getTag();
    }

    Food food = foodsList.get(position);

    holder.txtName.setText(food.getName());
    holder.txtPrice.setText(food.getPrice());

    byte[] foodImage = food.getImage();
    Bitmap bitmap = BitmapFactory.decodeByteArray(foodImage, 0, foodImage.length);
    holder.imageView.setImageBitmap(bitmap);


    return row;
}

}

我还有一个名为Food的类,代码也如下:

public class Food {

private String name;
private String price;
private byte[] image;

public Food(String name, String price, byte[] image) {
    this.name = name;
    this.price = price;
    this.image = image;

}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getPrice() {
    return price;
}
public void setPrice(String price) {
    this.price = price;
}
public byte[] getImage() {
    return image;
}
public void setImage(byte[] image) {
    this.image = image;
}

}

最后但并非最不重要的是,这是在初始化FoodList:

时崩溃的活动的代码
public class FoodList extends AppCompatActivity {

GridView gridView;
ArrayList<Food> list;
FoodListAdapter adapter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.food_list_activity);

    gridView =  findViewById(R.id.gridView);
    list = new ArrayList<>();
    adapter = new FoodListAdapter(this, R.layout.food_items, list);
    gridView.setAdapter(adapter);

    Cursor cursor = MainActivity.sqLiteHelper.getData("SELECT * FROM FOOD");
    list.clear();
    while (cursor.moveToNext()) {

        String name = cursor.getString(1);
        String price = cursor.getString(2);
        byte[] image = cursor.getBlob(3);

        list.add(new Food(name, price, image));
    }
    adapter.notifyDataSetChanged();
}

}

我不知道导致此错误的原因。希望有人可以解释我的问题......

1 个答案:

答案 0 :(得分:0)

Cursor cursor = MainActivity.sqLiteHelper.getData("SELECT * FROM FOOD");

将返回一个包含3列名称价格图片的光标,因此您将拥有偏移 0的列 名称 ), 1 价格 )和 2 图片 )。

因此, getString(2) 正在尝试获取作为BLOB的image列,但是作为 String ,因此尝试将BLOB转换为一个字符串。

如果它失败了那么你会因为getBlob(3)的索引错误而失败,因为没有偏移量为3的列。

最好不要正常使用偏移,而是使用 getColumnIndex(column_name) 方法,该方法根据给定的列名返回列偏移量(索引)。

因此,您可以使用以下方法来解决问题: -

    String name = cursor.getString(getColumnIndex("name"));
    String price = cursor.getString(getColumnIndex("price"));
    byte[] image = cursor.getBlob(getColumnIndex("image"));