基于Android-29
1.通過decodeFile
獲取bitmap
decodeFile(String pathName)
進(jìn)行方法重載的調(diào)用
decodeFile(String pathName, Options opts)
然后,會(huì)根據(jù)文件路徑pathName
,創(chuàng)建一個(gè)fileInputStream
最終去調(diào)用decodeStream
stream = new FileInputStream(pathName);
bm = decodeStream(stream, null, opts);
重點(diǎn)出現(xiàn)了,decodeStream,
我們先暫停一下,看一下其他獲取bitmap
的方法
2.通過decodeFileDescriptor
取bitmap
decodeFileDescriptor(FileDescriptor fd)
接下來會(huì)同樣進(jìn)行方法重載的調(diào)用
decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts)
在這里面我們先摘取關(guān)鍵代碼看一下
if (nativeIsSeekable(fd)) {
bm = nativeDecodeFileDescriptor(fd, outPadding, opts,
Options.nativeInBitmap(opts),
Options.nativeColorSpace(opts));
//同樣有重點(diǎn),步驟1,native方法
} else {
FileInputStream fis = new FileInputStream(fd);
try {
bm = decodeStreamInternal(fis, outPadding, opts); //同樣有重點(diǎn),步驟2
} finally {
try {
fis.close();
} catch (Throwable t) {/* ignore */}
}
}
setDensityFromOptions(bm, opts);//同樣有重點(diǎn),步驟3
這里是通 過``nativeDecodeFileDescriptor或者
decodeStreamInternal步驟獲取到bitmap,然后再通過步驟3給bitmap設(shè)置
desity`,
關(guān)鍵方法 nativeDecodeFileDescriptor
與 ecodeStreamInternal
3.通過decodeByteArray
獲取bitmap
decodeByteArray(byte[] data, int offset, int length)
同樣的會(huì)進(jìn)行方法重載調(diào)用
decodeByteArray(byte[] data, int offset, int length, Options opts)
在這里面我們摘取主要代碼看一下
bm = nativeDecodeByteArray(data, offset, length, opts,
Options.nativeInBitmap(opts),
Options.nativeColorSpace(opts));//步驟1,調(diào)用native方法獲取bitmap
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);//步驟2,給目標(biāo)bitmap設(shè)置desity
這個(gè)方法里面就比較直接,調(diào)用nativeDecodeByteArray
方法獲取到bitmap后,根據(jù)options給bitmap設(shè)置Desity
屬性
4.通過decodeResource
獲取bitmap
decodeResource(Resources res, int id)
同樣進(jìn)行方法重載
decodeResource(Resources res, int id, Options opts)
這里面有一處主要的代碼
final TypedValue value = new TypedValue();
InputStream is = null;
is = res.openRawResource(id, value);//獲取到inputStream,注意
bm = decodeResourceStream(res, value, is, null, opts);
//調(diào)用這個(gè),此時(shí)value.density已經(jīng)有值,會(huì)將資源文件對應(yīng)目錄的dpi設(shè)置給value.density后面會(huì)使用
那decodeResourceStream(res, value, is, null, opts);
是什么呢,同樣是查看源碼
public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
@Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
if (opts == null) {
opts = new Options();
}
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
} //這一部分主要是設(shè)置desity來讓bitmap所使用
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}//這一部分主要是設(shè)置目標(biāo)desity來讓bitmap所使用
return decodeStream(is, pad, opts);//又到了decodeStream,似曾相識(shí)的感覺
}
5.通過decodeStream
獲取bitmap
decodeStream(InputStream is)
方法重載調(diào)用
decodeStream(@Nullable InputStream is, @Nullable Rect outPadding,
@Nullable Options opts)
那我們就仔細(xì)的看一下這個(gè)就去的具體實(shí)現(xiàn)
if (is instanceof AssetManager.AssetInputStream) {
final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
bm = nativeDecodeAsset(asset, outPadding, opts, Options.nativeInBitmap(opts), Options.nativeColorSpace(opts));//方式一,通過asset資源獲取的輸入流
} else {
bm = decodeStreamInternal(is, outPadding, opts); //方式二,其他情況得到的輸入流
}
if (bm == null && opts != null && opts.inBitmap != null) {
throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);//設(shè)置desity
方式一已經(jīng)調(diào)用了native方法,看一下方式二的具體實(shí)現(xiàn)
decodeStreamInternal(@NonNull InputStream is,
@Nullable Rect outPadding, @Nullable Options opts)
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
return nativeDecodeStream(is, tempStorage, outPadding, opts,
Options.nativeInBitmap(opts),
Options.nativeColorSpace(opts));
方式二 也是走到了native方法里面.
我們在進(jìn)入native方法之前先來進(jìn)行一個(gè)簡單地總結(jié):
- 通過
decodeFile
獲取bitmap會(huì)最終走到decodeStream
- 通過
decodeFileDescriptor
獲取bitmap,最終會(huì)走到nativeDecodeFileDescriptor
或者decodeStreamInternal
- 通過
decodeByteArray
獲取bitmap,最終會(huì)走到nativeDecodeByteArray
- 通過
decodeResource
獲取bitmap,最終會(huì)走到decodeStream
- 通過
decodeStream
獲取bitmap,最終會(huì)走到nativeDecodeAsset
或者decodeStreamInternal
-
decodeStreamInternal
方式最終會(huì)走到nativeDecodeStream
綜上所述,最終獲取bitmap的方法都會(huì)調(diào)用以下四種方式之一來進(jìn)行:
nativeDecodeFileDescriptor
nativeDecodeByteArray
nativeDecodeAsset
nativeDecodeStream
優(yōu)秀文章推薦
深入理解Android Bitmap的各種操作
Android中圖片壓縮分析(上)
Android中圖片壓縮分析(下)
Bitmap 在內(nèi)存中的實(shí)際大小
Android中詳細(xì)的Bitmap
Bitmap 加載耗時(shí)長、占用內(nèi)存高,如何優(yōu)化?
Android一整套圖片解決方案
Android 系統(tǒng)自帶圖片裁剪功能(適配7.0跌帐、8.0楼吃、小米))
Bitmap 質(zhì)量壓縮 以及bitmap保存變大的原因