当您开始从Android应用程序将数据缓存到本地数据库时,迟早也需要将图像保存在该数据库中。 例如,如果您要存储有关用户在现场进行的观察的报告,该报告随后将上传到主系统,则可以方便地添加图片以更好地描述问题。
存储这些图像的第一个想法是将它们直接保存为BLOB(二进制大对象)到数据库中。 它可以工作,但这并不是最有效的方法,因为SQLite旨在存储值而不是大的二进制值。 另外,本地数据库很快就会变得很大,尤其是如果您需要保存完整大小,高质量的图片时。 如果您想对性能有一个更好的了解,可以在官方SQLite网站上找到一个基准,网址为https://www.sqlite.org/intern-v-extern-blob.html 。
在这种情况下,您真正想做的是仅在数据库中保留映像的路径,并将映像保存在应用程序的内部存储中。 当需要使用映像时,只需使用路径即可从文件系统中获取映像。 我建议您将图片保存到内部存储器中,因为它只能从您的应用程序访问,并且随时可用; 实际上,SQLite数据库本身也存储在内部存储中。
这是一个如何将图像添加到现有报表,将其保存在内部存储中以及将路径保留在数据库中的示例。 要了解有关如何创建数据库并将数据存储到数据库的更多信息,请阅读有关保存到SQLite数据库的文章 。
public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
* Updates the current picture for the report.
*
* @param reportId the identifier of the report for which to save the picture
* @param picture the picture to save to the internal storage and save path in the database.
*/
public void updateReportPicture(long reportId, Bitmap picture) {
// Saves the new picture to the internal storage with the unique identifier of the report as
// the name. That way, there will never be two report pictures with the same name.
String picturePath = "";
File internalStorage = mContext.getDir("ReportPictures", Context.MODE_PRIVATE);
File reportFilePath = new File(internalStorage, reportId + ".png");
String picturePath = reportFilePath.toString();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(reportFilePath);
picture.compress(Bitmap.CompressFormat.PNG, 100 /*quality*/, fos);
fos.close();
}
catch (Exception ex) {
Log.i("DATABASE", "Problem updating picture", ex);
picturePath = "";
}
// Updates the database entry for the report to point to the picture
SQLiteDatabase db = getWritableDatabase();
ContentValues newPictureValue = new ContentValues();
newPictureValue.put(ReportContract.ReportEntry.COLUMN_PICTURE_TITLE,
picturePath);
db.update(ReportContract.TABLE_NAME,
newPictureValue,
ReportContract.ReportEntry._ID + "=?",
new String[]{String.valueOf(reportId)});
}
}
如果将图片保存到数据库,则还需要一种获取图片以在应用程序中显示图片的方法。 以下是获取刚刚保存的图像以再次显示的方法:
public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
* Gets the picture for the specified report in the database.
*
* @param reportId the identifier of the report for which to get the picture.
*
* @return the picture for the report, or null if no picture was found.
*/
public Bitmap getReportPicture(long reportId) {
String picturePath = getReportPicturePath(reportId);
if (picturePath == null || picturePath.length() == 0)
return (null);
Bitmap reportPicture = BitmapFactory.decodeFile(picturePath);
return (reportPicture);
}
/**
* Gets the path of the picture for the specified report in the database.
*
* @param reportId the identifier of the report for which to get the picture.
*
* @return the picture for the report, or null if no picture was found.
*/
private String getReportPicturePath(long reportId) {
// Gets the database in the current database helper in read-only mode
SQLiteDatabase db = getReadableDatabase();
// After the query, the cursor points to the first database row
// returned by the request
Cursor reportCursor = db.query(ReportContract.TABLE_NAME,
null,
ReportContract.ReportEntry._ID + "=?",
new String[]{String.valueOf(reportId)},
null,
null,
null);
reportCursor.moveToNext();
// Get the path of the picture from the database row pointed by
// the cursor using the getColumnIndex method of the cursor.
String picturePath = reportCursor.getString(reportCursor.
getColumnIndex(ReportContract.ReportEntry.COLUMN_PICTURE_TITLE));
return (picturePath);
}
}
最后,如果您从数据库中删除关联的记录,则需要确保从内部存储器中删除图片。 如果保留这些图片,则应用程序使用的内部存储会随着时间的推移而变大,并且您的用户将无法删除这些图片,因为内部存储已被隐藏。
public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
* Deletes the specified report from the database, removing also the associated picture from the
* internal storage if any.
*
* @param reportId the report to remove.
*/
public void deleteReport(long reportId) {
// Remove picture for report from internal storage
String picturePath = getReportPicturePath(reportId); // See above
if (picturePath != null && picturePath.length() != 0) {
File reportFilePath = new File(picturePath);
reportFilePath.delete();
}
// Remove the report from the database
SQLiteDatabase db = getWritableDatabase();
db.delete(ReportContract.TABLE_NAME,
ReportContract.ReportEntry._ID + "=?",
new String[]{String.valueOf(reportId)});
}
}