Android Base64转图片
最近做一个项目里面有关于图片展示的需求,但是任性的后台跟我说没有图片服务器,只能给我base64让我自己转成图片,好吧,我忍,转就转吧。。
首先第一步咱还是谦虚点上百度查查别人咋转的,结果似乎各位码友关于这方面的需求还是不多啊,查来查去普遍的是这样的:
/** * bitmap转为base64 * @param bitmap * @return */ public static String bitmapToBase64(Bitmap bitmap) { String result = null; ByteArrayOutputStream baos = null; try { if (bitmap != null) { baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); baos.flush(); baos.close(); byte[] bitmapBytes = baos.toByteArray(); result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (baos != null) { baos.flush(); baos.close(); } } catch (IOException e) { e.printStackTrace(); } } return result; } /** * base64转为bitmap * @param base64Data * @return */ public static Bitmap base64ToBitmap(String base64Data) { byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); }
楼主主要用到了base64转bitmap的方法,这个方法看上去没什么毛病,but。。。但是。。BitmapFactory.decodeByteArray这个方法是很邪恶的,BitmapFactory每次都会为新decode的bitmap分配内存,所以很容易造成oom,楼主为求真实性,手动刷新了几下我们的页面,然后就看着内存蹭蹭的往上涨,结果很快就oom了,所以这个所谓的往上代码并不可取,果断抛弃了,自己来改造一个,贴上自己的代码(Kotlin版本):
object ImageUtil { private var mMemoryCache: LruCache<String, Bitmap> ?= null private var cacheSize:Int = 0 /** * bitmap转为base64 * @param bitmap * @return */ public fun bitmapToBase64(bitmap: Bitmap): String { var result = "" var baos: ByteArrayOutputStream? = null try { if (bitmap != null) { baos = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos) baos!!.flush() baos!!.close() val bitmapBytes = baos!!.toByteArray() result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT) } } catch (e: IOException) { e.printStackTrace() } finally { try { if (baos != null) { baos!!.flush() baos!!.close() } } catch (e: IOException) { e.printStackTrace() } } return result } /** * base64转为bitmap * @param base64Data * @return */ public fun base64ToBitmap(base64Data: String): Bitmap? { if(cacheSize == 0){ // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。 // LruCache通过构造函数传入缓存值,以KB为单位。 val maxMemory = Runtime.getRuntime().maxMemory() / 1024 // 使用最大可用内存值的1/8作为缓存的大小。 cacheSize = (maxMemory / 8).toInt() } if(mMemoryCache == null){ mMemoryCache = object : LruCache<String, Bitmap>(cacheSize) { override fun sizeOf(key: String?, bitmap: Bitmap?): Int { // 重写此方法来衡量每张图片的大小,默认返回图片数量。 return bitmap!!.byteCount / 1024 } } } var bitmap: Bitmap? = null var imgByte: ByteArray? = null var inputStream:InputStream ?= null try { mMemoryCache?.get(base64Data)?.let { bitmap = it } if(bitmap == null){ imgByte = Base64.decode(base64Data, Base64.DEFAULT) val option = BitmapFactory.Options() option.inSampleSize = 2 option.inTempStorage = ByteArray(5*1024*1024) inputStream = ByteArrayInputStream(imgByte) val softReference = SoftReference(BitmapFactory.decodeStream(inputStream, null, option)) bitmap = softReference.get() softReference.clear() mMemoryCache?.put(base64Data, bitmap) } } catch (e: Exception) { e.printStackTrace() }finally { imgByte = null try { inputStream?.close() System.gc() } catch (e: IOException) { e.printStackTrace() } } return bitmap } }
通过内存缓存机制加上软应用,保证同一张图片只decode一次,改完之后还算满意,基本上内存可以保持稳定,好了,先到这了,有啥写的不好的多多见谅,或者可以共同探讨。。