如何将含ImageSpan的EditText图文正确存取到SQLite数据库
问题说明
已在EditText中实现图片插入功能,运行正常,现需要将EditText内的全部内容(文本+图片)存储到SQLite数据库。实际存储后读取数据时仅能显示文本内容,图片无法正常展示,已尝试调用Html.toHtml()和Html.fromHtml()方法处理内容,方案未生效。
现有实现代码
插入图片到EditText的代码
Uri imageUri= data.getData(); InputStream inputStream= getContentResolver().openInputStream(imageUri); Bitmap bitmap= BitmapFactory.decodeStream(inputStream); final Drawable drawable = new BitmapDrawable(getResources(), bitmap); drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); final ImageSpan imageSpan = new ImageSpan(drawable,ImageSpan.ALIGN_BOTTOM); SpannableStringBuilder span = new SpannableStringBuilder(editText.getText()+".\n"); span.setSpan(imageSpan, 0, (".\n").length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editText.append(span, 0, (".\n").length());
存储内容到数据库的代码
String textWithImage= Html.toHtml(editText.getText()); Note note = new Note(textWithImage); Databse databse= new Databse(this); databse.insertInDB(note);
从数据库读取内容的代码
databse= new Databse(this); note= databse.getSingleNote(noteId); String text= note.getNoteText(); editText.setText(Html.fromHtml(text));
失效原因
- 系统自带的
Html.toHtml()默认无法识别内存中动态生成的ImageSpan绑定的Bitmap,不会生成有效的<img>标签,存储的HTML内容里本身就没有图片信息。 - 无自定义配置的
Html.fromHtml()遇到<img>标签时没有对应的图片加载逻辑,就算标签存在也无法正常渲染图片。
可行实现方案
不要依赖系统Html类的默认转换逻辑,自行实现富文本内容的序列化与反序列化:
存储阶段
遍历EditText返回的Spannable内容,拆分普通文本与图片资源:- 普通文本按顺序记录
- 每遇到一个
ImageSpan,取出对应的Bitmap,要么压缩后转Base64字符串,要么存储到应用私有目录拿到本地文件路径;给每个图片生成唯一占位标记(比如[img:序号]),插入到文本对应图片位置,同时建立「占位标记-图片数据/路径」的映射关系 - 最后把带占位符的文本、图片映射关系统一序列化为JSON字符串,存入SQLite即可
核心参考代码:
Spannable originContent = editText.getText(); ImageSpan[] allImageSpans = originContent.getSpans(0, originContent.length(), ImageSpan.class); JSONObject storeData = new JSONObject(); JSONArray imageArray = new JSONArray(); String contentText = originContent.toString(); // 自行实现文本替换逻辑:遍历每个ImageSpan,找到它在文本中的位置,替换为对应[img:i]标记 for (int i = 0; i < allImageSpans.length; i++) { BitmapDrawable drawable = (BitmapDrawable) allImageSpans[i].getDrawable(); Bitmap bitmap = drawable.getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); // 压缩图片减少体积 bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream); String imgBase64 = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT); JSONObject imgItem = new JSONObject(); imgItem.put("pos", i); imgItem.put("source", imgBase64); imageArray.put(imgItem); } storeData.put("content", processedTextWithPlaceholder); storeData.put("imgList", imageArray); // 把storeData.toString()存入数据库提示:如果插入的图片体积较大,不建议直接存Base64到数据库,优先把图片存到应用私有目录,数据库只存图片本地路径,避免数据库文件过大拖慢读写速度。
读取阶段
从数据库取出存储的JSON字符串,解析出带占位符的文本和图片列表:- 先把带占位符的文本传入
SpannableStringBuilder - 遍历文本找到所有
[img:序号]格式的占位符,根据序号取出对应图片数据(Base64转Bitmap,或者按路径读取本地图片),生成对应大小的Drawable和ImageSpan,替换掉占位符文本,给对应位置设置Span - 处理完成后把
SpannableStringBuilder设置给EditText即可正常显示图文混排内容。
- 先把带占位符的文本传入
如果一定要用HTML格式存储,需要自定义Html.toHtml()的标签生成逻辑,给每个ImageSpan生成带自定义标识的<img>标签,读取时给Html.fromHtml()传入自定义的ImageGetter实现,根据标签里的标识加载对应图片,才能正常渲染。
内容的提问来源于stack exchange,提问作者MS Moshiur
相关产品推荐
相关产品推荐

