方法一
按照給定尺寸進(jìn)行圖片的解碼仰禀,而不是解碼整個(gè)圖片的尺寸坡椒,用來(lái)減少內(nèi)存的占用奥帘。
官方文檔:
https://api.flutter.dev/flutter/painting/ResizeImage-class.html
官方說(shuō)明:
Instructs Flutter to decode the image at the specified dimensions instead of at its native size.
This allows finer control of the size of the image in ImageCache and is generally used to reduce the memory footprint of ImageCache.
The decoded image may still be displayed at sizes other than the cached size provided here.
使用:
Image(
image: ResizeImage(
NetworkImage('https://img-dev.xinxigu.com.cn/s1/2021/1/18/6e19c84b1b4aeb416bdee40615aa9854.jpg'),
width: AdaptUtils.pxW(150).toInt(),
height: AdaptUtils.pxW(150).toInt(),
),
),
方法二
三方庫(kù):cached_network_image
限2.5.0之后版本才可用
設(shè)定最大的緩存寬度和高度this.maxWidthDiskCache
猾骡、this.maxHeightDiskCache
CachedNetworkImage({
Key key,
@required this.imageUrl,
this.httpHeaders,
this.imageBuilder,
this.placeholder,
this.progressIndicatorBuilder,
this.errorWidget,
this.fadeOutDuration = const Duration(milliseconds: 1000),
this.fadeOutCurve = Curves.easeOut,
this.fadeInDuration = const Duration(milliseconds: 500),
this.fadeInCurve = Curves.easeIn,
this.width,
this.height,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.matchTextDirection = false,
this.cacheManager,
this.useOldImageOnUrlChange = false,
this.color,
this.filterQuality = FilterQuality.low,
this.colorBlendMode,
this.placeholderFadeInDuration,
this.memCacheWidth,
this.memCacheHeight,
this.cacheKey,
this.maxWidthDiskCache,
this.maxHeightDiskCache,
使用:
CachedNetworkImage(
imageUrl: AppUtils.processImageUrl(url: coverUrl) ?? AppURL.defaultImageRectangle,
width: AdaptUtils.pxW(150),
height: AdaptUtils.pxW(150),
fit: BoxFit.cover,
placeholder: AppURL.placeholderRectangle(
width: AdaptUtils.pxW(150),
height: AdaptUtils.pxW(150),
),
maxWidthDiskCache: AdaptUtils.pxW(150 * 2).toInt(),
maxHeightDiskCache: AdaptUtils.pxW(150 * 2).toInt(),
),
方法三
從相冊(cè)選取圖片洪规,展示時(shí)使用指定尺寸寬高進(jìn)行處理旧困。
使用三方庫(kù):
# 仿微信資源選擇器
wechat_assets_picker: ^4.2.0
# 仿微信拍照
wechat_camera_picker: ^1.2.1
使用自定義provider
來(lái)指定所需圖片的寬高:
/// The item builder for images and video type of asset.
/// 圖片和視頻資源的部件構(gòu)建
/// 縮略圖視圖
static Widget thumbImageItemBuilder(
BuildContext context,
AssetEntity asset, // 圖片資源數(shù)據(jù)
double thumbSizeWidth, // 縮略圖寬醇份,同為圖片展示寬
double thumbSizeHeight, // 縮略圖高,同為圖片展示高
BoxFit fit, // 圖片展示方式
) {
final AssetEntityImageProvider imageProvider = AssetEntityImageProvider(
asset,
isOriginal: false,
thumbSize: [int.parse('${thumbSizeWidth.toStringAsFixed(0)}'), int.parse('${thumbSizeWidth.toStringAsFixed(0)}')],
);
return RepaintBoundary(
child: Image(
width: thumbSizeWidth,
height: thumbSizeHeight,
image: imageProvider,
fit: fit,
),
);
}
AssetEntityImageProvider
傳入寬高和圖片原圖AssetEntity
數(shù)據(jù)吼具。
provider
中key.entity.thumbDataWithSize
方法:
Future<ui.Codec> _loadAsync(
AssetEntityImageProvider key,
DecoderCallback decode,
) async {
assert(key == this);
Uint8List data;
if (isOriginal ?? false) {
if (imageFileType == ImageFileType.heic) {
data = await (await key.entity.file).readAsBytes();
} else {
data = await key.entity.originBytes;
}
} else {
data = await key.entity.thumbDataWithSize(thumbSize[0], thumbSize[1]);
}
return decode(data);
}
進(jìn)入entity
中thumbDataWithSize
方法:
/// get thumb with size
Future<Uint8List> thumbDataWithSize(
int width,
int height, {
ThumbFormat format = ThumbFormat.jpeg,
int quality = 100,
}) {
assert(width > 0 && height > 0, "The width and height must better 0.");
assert(format != null, "The format must not be null.");
assert(quality > 0 && quality <= 100, "The quality must between 0 and 100");
/// Return null if asset is audio or other type, because they don't have such a thing.
if (type == AssetType.audio || type == AssetType.other) {
return null;
}
return PhotoManager._getThumbDataWithId(
id,
width: width,
height: height,
format: format,
quality: quality,
);
}
進(jìn)入_getThumbDataWithId
方法中僚纷,
static _getThumbDataWithId(
String id, {
int width = 150,
int height = 150,
ThumbFormat format = ThumbFormat.jpeg,
int quality = 100,
}) {
return _plugin.getThumb(
id: id,
width: width,
height: height,
format: format,
quality: quality,
);
}
進(jìn)入getThumb:
Future<Uint8List> getThumb({
@required String id,
int width = 100,
int height = 100,
ThumbFormat format,
int quality,
}) {
return _channel.invokeMethod("getThumb", {
"width": width,
"height": height,
"id": id,
"format": format.index,
"quality": quality,
});
}
調(diào)用iOS原生的獲取圖片方法,
if ([call.method isEqualToString:@"getThumb"]) {
NSString *id = call.arguments[@"id"];
NSUInteger width = [call.arguments[@"width"] unsignedIntegerValue];
NSUInteger height = [call.arguments[@"height"] unsignedIntegerValue];
NSUInteger format = [call.arguments[@"format"] unsignedIntegerValue];
NSUInteger quality = [call.arguments[@"quality"] unsignedIntegerValue];
[manager getThumbWithId:id width:width height:height format:format quality:quality resultHandler:handler];
}
進(jìn)入getThumbWithId
方法拗盒,
- (void)getThumbWithId:(NSString *)id width:(NSUInteger)width height:(NSUInteger)height format:(NSUInteger)format quality:(NSUInteger)quality resultHandler:(ResultHandler *)handler {
PMAssetEntity *entity = [self getAssetEntity:id];
if (entity && entity.phAsset) {
PHAsset *asset = entity.phAsset;
[self fetchThumb:asset width:width height:height format:format quality:quality resultHandler:handler];
} else {
[handler replyError:@"asset is not found"];
}
}
原生實(shí)現(xiàn)獲取置頂寬高縮略圖方法實(shí)現(xiàn):
使用iOS
原生類PHImageManager
的
targetSize:CGSizeMake(width, height)
contentMode:PHImageContentModeAspectFill
options:options
resultHandler:^(UIImage *result, NSDictionary *info)
來(lái)獲取縮略圖怖竭。
- (void)fetchThumb:(PHAsset *)asset width:(NSUInteger)width height:(NSUInteger)height format:(NSUInteger)format quality:(NSUInteger)quality resultHandler:(ResultHandler *)handler {
PHImageManager *manager = PHImageManager.defaultManager;
PHImageRequestOptions *options = [PHImageRequestOptions new];
[options setNetworkAccessAllowed:YES];
[options setProgressHandler:^(double progress, NSError *error, BOOL *stop,
NSDictionary *info) {
if (progress == 1.0) {
[self fetchThumb:asset width:width height:height format:format quality:quality resultHandler:handler];
}
}];
[manager requestImageForAsset:asset
targetSize:CGSizeMake(width, height)
contentMode:PHImageContentModeAspectFill
options:options
resultHandler:^(UIImage *result, NSDictionary *info) {
BOOL downloadFinished = [PMManager isDownloadFinish:info];
if (!downloadFinished) {
return;
}
if ([handler isReplied]) {
return;
}
NSData *imageData;
if (format == 1) {
imageData = UIImagePNGRepresentation(result);
} else {
double qualityValue = (double) quality / 100.0;
imageData = UIImageJPEGRepresentation(result, qualityValue);
}
FlutterStandardTypedData *data = [FlutterStandardTypedData typedDataWithBytes:imageData];
[handler reply:data];
}];
}