我在 flutter 中使用 Riverpod 进行状态管理。我需要让用户选择一个图像,裁剪它,在将其上传到服务器之前暂时存储它。因此,我正在考虑将图像存储在 Riverpod 提供程序中,该提供程序保存也应该上传的其他数据。 Riverpod可以存储这样的图像吗?这是一个好方法吗?如果没有,为什么?更好的方法是什么?
可以参考这个代码
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'buttons.dart';
part 'image_cropper.g.dart';
/// Provider to temporarily hold cropped image.
@riverpod
class CroppedImage extends _$CroppedImage {
@override
XFile? build() {
return null;
}
}
/// Crop image.
Future<XFile> cropImage(
BuildContext context,
XFile imageFile,
) async {
final croppedFile = await ImageCropper().cropImage(
sourcePath: imageFile.path,
aspectRatio: const CropAspectRatio(
ratioX: 1,
ratioY: 2,
),
uiSettings: [
// Android setting.
AndroidUiSettings(
toolbarColor: Colors.black,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.ratio5x4,
lockAspectRatio: true,
hideBottomControls: true,
),
// iOS setting.
IOSUiSettings(
minimumAspectRatio: 1,
rotateButtonsHidden: true,
aspectRatioPickerButtonHidden: true,
),
// Web settings.
WebUiSettings(
context: context,
presentStyle: CropperPresentStyle.page,
barrierColor: AppColors.blackOverlayColor,
showZoomer: true,
enableZoom: true,
boundary: CroppieBoundary(
width: context.screenAppWidth.toInt(),
height: context.screenAppWidth * 5 ~/ 4,
),
viewPort: CroppieViewPort(
width: (context.screenAppWidth * .9).toInt(),
height: context.screenAppWidth * .9 * 5 ~/ 4,
),
customRouteBuilder: (cropper, crop, _) {
return MaterialPageRoute(
builder: (context) {
return CropperPage(
cropper: cropper,
crop: crop,
cropperContainerWidth: context.screenAppWidth,
cropperContainerHeight:
(context.screenAppWidth * 5 ~/ 4).toDouble(),
);
},
);
},
),
],
);
if (croppedFile == null) {
throw ImagePickerException.failedCrop();
}
return XFile(croppedFile.path);
}
class CropperPage extends StatelessWidget {
const CropperPage({
super.key,
required this.cropper,
required this.crop,
required this.cropperContainerWidth,
required this.cropperContainerHeight,
});
final Widget cropper;
final Future<String?> Function() crop;
final double cropperContainerWidth;
final double cropperContainerHeight;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
CommonTextButton(
text: '提出する',
onPressed: () async {
final result = await crop();
if (context.mounted) {
Navigator.of(context).pop(result);
}
},
),
],
),
body: Column(
children: [
const Gap(16),
const Text('※画像のトリミングに失敗する場合は縦横比率を調整ください。', style: TextStyle(fontSize: 12),),
const Gap(16),
Center(
child: SizedBox(
width: cropperContainerWidth,
height: cropperContainerHeight,
child: cropper,
),
),
],
),
);
}
}
用途:
final croppedImage = await cropImage(context, image);