Bitmap获取宽高
Bitmap获取宽高有2种方式,第一种是直接将Bitmap加载进内存中,然后通过测量拿到宽高。
private void getBitmapWH() {
Bitmap bitmap = BitmapFactory.decodeFile("file/img.jpg");
int width = bitmap.getWidth();
int height = bitmap.getHeight() ;
}
然后可以看看decodeFile的源码:
public static Bitmap decodeFile(String pathName) {
return decodeFile(pathName, null);
}
/**
* Decode a file path into a bitmap. If the specified file name is null,
* or cannot be decoded into a bitmap, the function returns null.
*
* @param pathName complete path name for the file to be decoded.
* @param opts null-ok; Options that control downsampling and whether the
* image should be completely decoded, or just is size returned.
* @return The decoded bitmap, or null if the image data could not be
* decoded, or, if opts is non-null, if opts requested only the
* size be returned (in opts.outWidth and opts.outHeight)
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
* and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
* is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
* function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeFile(String pathName, Options opts) {
validate(opts);
Bitmap bm = null;
InputStream stream = null;
try {
stream = new FileInputStream(pathName);
bm = decodeStream(stream, null, opts);
} catch (Exception e) {
/* do nothing.
If the exception happened on open, bm will be null.
*/
Log.e("BitmapFactory", "Unable to decode stream: " + e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// do nothing here
}
}
}
return bm;
}
特意贴出又臭又长、但很有用的注释,注释说会当下面几种情况会返回null:
1、image 数据无法被decode;
2、第二个参数Option不为空,并且Option只想拿到尺寸(通过设置Option的inJustDecodeBounds为true)
/**
* If set to true, the decoder will return null (no bitmap), but
* the <code>out...</code> fields will still be set, allowing the caller to
* query the bitmap without having to allocate the memory for its pixels.
*/
public boolean inJustDecodeBounds;
再次看Option里面的inJustDecodeBounds
注释,可以看到如果设置该属性为true
,则decodeFile不会返回Bitmap,而是返回null,但是返回前会设置一些outXXX的域信息,比如outWidth、outHeight,以便不分配内存就能知道Bitmap的宽高。这就是第二种方式:
private void getBitmapWH() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只拿取尺寸
Bitmap bitmap = BitmapFactory.decodeFile("file/img.jpg",options);
//此时拿取的 bitmap == null,上面有说道
int width = options.outWidth ;
int height = options.outHeight ;
}
Android OOM
参考资料:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html
OOM简单来说就是应用所需要的内存,大于系统能分配的内存,这时候应用会崩溃,系统会抛出OutOfMemoryError
异常。
如何避免:
1、减小Bitmap对象占用的内存,通过inSampleSize来限制尺寸,通过decode format来选择更小的解码方式
2、及时回收Bitmap对象
3、资源文件重复利用,避免定义多个同样的
4、内存对象重复利用,通过对象池,处理好复用逻辑,降低内存的分配与回收
5、ListView/GridView里面对于ContentView的复用
6、通过LRU机制缓存Bitmap,使用Options.inBitmap属性来制定当前Bitmap占用已经存在的内存区域,而不是重新分配。
7、自定义View中,避免在onDraw等频繁调用的方法里创建对象,这会引起频繁的GC,甚至内存抖动。
8、使用StringBuilder来替换+,由于String是不可变的,所以每次+都会重新创建新对象。
9、避免内存泄露
10、优化内存布局层次,减少内存消耗
11、使用更轻量级的数据结构,比如ArrayMap和SparseArray来替代HashMap等传统数据结构。
12、避免在Android中使用Enum
13、注意监听器的注销,例如调用registerReceiver()后未调用unregisterReceiver()
14、数据库的cursor及时关闭
15、及时关闭读写流
16、谨慎使用static变量