实现思路
- 定义Mixin:创建一个Mixin类,该类负责处理图片缓存和预加载逻辑。
- 缓存机制:使用一个
Map
来存储已经加载过的图片,键为图片的URL,值为对应的Image
对象。
- 预加载:在图片即将进入屏幕可视区域时,提前加载图片。可以通过监听滚动事件来判断图片是否接近可视区域。
主要代码结构
import 'package:flutter/material.dart';
// Mixin定义
mixin ImageCacheAndPreloadMixin<T extends StatefulWidget> on State<T> {
final Map<String, Image> imageCache = {};
Future<Image> getImage(String url) async {
if (imageCache.containsKey(url)) {
return imageCache[url]!;
} else {
final image = await precacheImage(NetworkImage(url), context);
imageCache[url] = image;
return image;
}
}
void preloadImages(List<String> urls, int visibleIndex) {
for (int i = visibleIndex - 2; i <= visibleIndex + 2; i++) {
if (i >= 0 && i < urls.length) {
getImage(urls[i]);
}
}
}
}
class ImageListWidget extends StatefulWidget {
final List<String> imageUrls;
const ImageListWidget({Key? key, required this.imageUrls}) : super(key: key);
@override
_ImageListWidgetState createState() => _ImageListWidgetState();
}
class _ImageListWidgetState extends State<ImageListWidget> with ImageCacheAndPreloadMixin<ImageListWidget> {
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(() {
final position = _scrollController.position;
final viewportHeight = position.viewportDimension;
final offset = position.pixels;
final totalHeight = position.maxScrollExtent;
final visibleIndex = (offset / viewportHeight).floor();
preloadImages(widget.imageUrls, visibleIndex);
});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
controller: _scrollController,
itemCount: widget.imageUrls.length,
itemBuilder: (context, index) {
return FutureBuilder<Image>(
future: getImage(widget.imageUrls[index]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Image(image: snapshot.data!);
}
},
);
},
);
}
}