但所发生的是所有加载的图像始终是
名单。
对于块中的图像,您有一个单独的流,因此GridView行中所有相应的StreamBuilder都将只使用快照中的最后一个值进行更新(最后一个图像即结束)。
如果你确定你只有一些图片
如果希望在GridView中显示,可以使用fetchImageByID()方法为特定图像创建流,保留对该图像的引用,然后返回该图像。然后,您可以将返回的流传递给row streambuilder,而不是mybloc.imagebyid,这样,您的rows streambuilder将具有不同的数据源。加载图像后,您可以将其添加到特定流(基于ID),并且您的行将仅使用该特定数据进行更新。一些代码:
//fetch the image
Observable<dynamic> imageStream = myBloc.fetchImageById(snapshot.data[index].Id.toString());
return StreamBuilder(
stream: imageStream,
builder: (context, AsyncSnapshot<dynamic> snapshotImg){
// rest of code
在您的集团中,您将拥有:
Map<String, PublishSubject<dynamic>> _backingImageStreams = HashMap()
Observable<dynamic> fetchImageById(String _id) {
PublishSubject<dynamic> backingImgStream = _backingImageStreams[id];
if (backingImgStream == null) {
backingImgStream = PublishSubject<dynamic>();
_backingImageStreams[id] = backingImgStream;
}
// i'm assuming that repository.fetchImageById() returns a Future ?!
_repository.fetchImageById(_id).then((){
_fetcherImage.sink.add(imgBinary);
});
return _fetcherImage.stream;
}
在一般情况下
,我认为您需要为FutureBuilder从StreamBuilder更改代码。在小部件中,您将拥有:
Widget buildList(AsyncSnapshot<List<Result>> snapshot) {
// ...
itemBuilder: (BuildContext context, int index) {
//fetch the image
Future<dynamic> imageFuture = myBloc.fetchImageById(snapshot.data[index].Id.toString());
return FutureBuilder(
future: imageFuture,
builder: (context, AsyncSnapshot<dynamic> snapshotImg){
// rest of your current code
然后您需要更改bloc方法fetchImageByID()。当您处理图像时,您将希望实现某种缓存,这样您将更高效:
-
如果你已经有了相同的图片,不要再下载它(并且要快速地将它显示给用户)
-
不能一次加载所有图像并使内存混乱(或完全失败)
集团代码:
class MyBloc {
// remove the imageId observable
// A primitive and silly cache. This will only make sure we don't make extra
// requests for images if we already have the image data, BUT if the user
// scrolls the entire GridView we will also have in memory all the image data.
// This should be replaced with some sort of disk based cache or something
// that limits the amount of memory the cache uses.
final Map<String, dynamic> cache = HashMap();
FutureOr<dynamic> fetchImageById(String _id) async {
// atempt to find the image in the cache, maybe we already downloaded it
dynamic image = cache[id];
// if we found an image for this id then we can simply return it
if (image != null) {
return image;
} else {
// this is the first time we fetch the image, or the image was previously disposed from the cache and we need to get it
dynamic image = // your code to fetch the image
// put the image in the cache so we have it for future requests
cache[id] = image;
// return the downloaded image, you could also return the Future of the fetch request but you need to add it to the cache
return image;
}
}
如果只想向用户显示图像,只需让fetchImageByID()从图像获取请求返回未来(但每次构建小部件时都会发出获取请求)。