【发布时间】:2020-12-31 08:25:27
【问题描述】:
我加载所有图像目录并加载我加载的目录中的所有图像路径。 (与storage_path)
我使用文件路径加载图像,所以我使用Image.file()。
但是,当我加载大图像文件(4032×3024 大小或 >3MB)时,加载非常缓慢。
像这样:
我不需要加载高分辨率的图像,因为图像小部件很小。
如何压缩或调整这些图像的大小?
或者有没有更好的解决方案?
代码:
// gallery_page.dart
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:listing/widget/bar_widget.dart';
import 'package:listing/provider/dark_mode_provider.dart';
import 'package:listing/page/sub/image/image_edit_page.dart';
import 'package:listing/page/sub/gallery/media_directory.dart';
import 'package:listing/util/image_types.dart';
import 'package:provider/provider.dart';
import 'package:storage_path/storage_path.dart';
enum GalleryType { IMAGE, VIDEO }
class GalleryPageArguments {
final GalleryType type;
GalleryPageArguments(this.type);
}
class GalleryPage extends StatelessWidget {
static final routeName = '/gallery_page';
@override
Widget build(BuildContext context) {
GalleryPageArguments arguments = ModalRoute.of(context).settings.arguments;
GalleryType type = arguments.type;
ColorPalette palette = Provider.of<DarkModeProvider>(context).colorPallette;
Future<List<MediaDirectory>> getPath;
if(type == GalleryType.IMAGE) {
getPath = _getImagePaths();
} else {
getPath = _getVideoPaths();
}
return Scaffold(
body: SafeArea(
child: FutureBuilder<List<MediaDirectory>>(
future: getPath,
builder: (context, snapshot) {
if(snapshot.hasData) {
HashMap<String, MediaDirectory> mediaDirsMap = new HashMap<String, MediaDirectory>();
List<MediaDirectory> mediaDirs = snapshot.data;
for(MediaDirectory mediaDir in mediaDirs) {
mediaDirsMap.putIfAbsent(mediaDir.dirName, () => mediaDir);
}
return _InnerGalleryPage(palette, mediaDirsMap);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
Future<List<MediaDirectory>> _getImagePaths() async {
String imagesPath = await StoragePath.imagesPath;
dynamic response = jsonDecode(imagesPath);
List<dynamic> imageDirJsonList = List.from(response);
List<MediaDirectory> imageDirList = imageDirJsonList.map((imageDirJson) => MediaDirectory.fromJson(imageDirJson, GalleryType.IMAGE)).toList();
return imageDirList;
}
Future<List<MediaDirectory>> _getVideoPaths() async {
String videoPath = await StoragePath.videoPath;
dynamic response = jsonDecode(videoPath);
List<dynamic> videoDirJsonList = List.from(response);
List<MediaDirectory> imageDirList = videoDirJsonList.map((imageDirJson) => MediaDirectory.fromJson(imageDirJson, GalleryType.VIDEO)).toList();
return imageDirList;
}
}
class _InnerGalleryPage extends StatefulWidget {
final ColorPalette _palette;
final HashMap<String, MediaDirectory> _mediaDirs;
_InnerGalleryPage(this._palette, this._mediaDirs);
@override
_InnerGalleryPageState createState() => _InnerGalleryPageState();
}
class _InnerGalleryPageState extends State<_InnerGalleryPage> {
String currentSelectedDir;
@override
void initState() {
super.initState();
String firstDir = widget._mediaDirs.keys.toList()[0];
currentSelectedDir = widget._mediaDirs[firstDir].dirName;
}
@override
Widget build(BuildContext context) {
HashMap<String, MediaDirectory> mediaDirs = widget._mediaDirs;
return BarWidget(
titleWidget: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: currentSelectedDir,
items: mediaDirs.keys.map(
(mediaDirName) {
return DropdownMenuItem(
value: mediaDirName,
child: Text(mediaDirName),
);
}
).toList(),
onChanged: (changedDir) {
setState(() {
currentSelectedDir = changedDir;
});
},
)
),
palette: widget._palette,
child: Container(
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1,
crossAxisSpacing: 5,
mainAxisSpacing: 5
),
itemBuilder: (context, index) {
String imagePath = mediaDirs[currentSelectedDir].mediaFiles[index].path;
ImageTypes imageType = getImageTypesFromPath(imagePath);
return GestureDetector(
child: _getImage(imagePath),
onTap: () {
if(imageType == ImageTypes.GIF) {
File imageFile = File(imagePath);
Image pickedImage = Image.file(imageFile);
Navigator.pop(context, pickedImage);
} else {
File imageFile = File(imagePath);
Image pickedImage = Image.file(imageFile);
Navigator.pushNamed(context, ImageEditPage.routeName, arguments: ImageEditPageArguments(pickedImage, imagePath, imageType)).then((result) {
if(result is Image) {
Navigator.pop(context, result);
}
});
}
}
);
},
itemCount: mediaDirs[currentSelectedDir].mediaFilesCount,
)
),
);
}
Image _getImage(String filePath) {
File imageFile = File(filePath);
Image image = Image.file(imageFile, fit: BoxFit.cover);
return image;
}
}
// media_directory.dart
import 'dart:convert';
import 'package:listing/page/sub/gallery/gallery_page.dart';
import 'package:listing/page/sub/gallery/media_file.dart';
class MediaDirectory {
final String _dirName;
final List<MediaFile> _mediaFiles;
String get dirName => _dirName;
int get mediaFilesCount => _mediaFiles.length;
List<MediaFile> get mediaFiles => _mediaFiles;
MediaDirectory(this._dirName, this._mediaFiles);
factory MediaDirectory.fromJsonString(String jsonString, GalleryType type) {
return MediaDirectory.fromJson(jsonDecode(jsonString), type);
}
factory MediaDirectory.fromJson(dynamic json, GalleryType type) {
String dirName = json['folderName'];
List<MediaFile> mediaFiles = [];
if(type == GalleryType.IMAGE) {
List<String> paths = List.from(json['files']);
mediaFiles = paths.map((path) => ImageFile(path)).toList();
} else if(type == GalleryType.VIDEO) {
List<dynamic> files = List.from(json['files']);
mediaFiles = files.map((fileJson) => VideoFile.fromJson(fileJson)).toList();
}
return MediaDirectory(dirName, mediaFiles);
}
}
// media_file.dart
import 'dart:convert';
import 'package:flutter/material.dart';
class MediaFile {
final String _path;
String get path => _path;
MediaFile(this._path);
}
class ImageFile extends MediaFile {
ImageFile(String path) : super(path);
}
class VideoFile extends MediaFile {
final String _fileName;
final int _addedDate;
final int _duration;
final int _size;
String get fileName => _fileName;
int get addedDate => _addedDate;
int get duration => _duration;
int get size => _size;
VideoFile({
@required String path,
@required String fileName,
@required int addedDate,
@required int duration,
@required int size
})
: assert(path != null),
assert(fileName != null),
assert(addedDate != null),
assert(duration != null),
assert(size != null),
this._fileName = fileName,
this._addedDate = addedDate,
this._duration = duration,
this._size = size,
super(path);
factory VideoFile.fromJsonString(String jsonString) {
return VideoFile.fromJsonString(jsonDecode(jsonString));
}
factory VideoFile.fromJson(dynamic json) {
String path = json['path'];
String fileName = json['displayName'];
int addedDate = int.parse(json['dateAdded']);
int duration = int.parse(json['duration']);
int size = int.parse(json['size']);
return VideoFile(path: path, fileName: fileName, addedDate: addedDate, duration: duration, size: size);
}
}
如果你需要其他代码来解决这个问题,我可以给你你需要的代码。
谢谢。
【问题讨论】: