Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 如何防止FutureBuilder在加载时更改旧小部件?_Flutter - Fatal编程技术网

Flutter 如何防止FutureBuilder在加载时更改旧小部件?

Flutter 如何防止FutureBuilder在加载时更改旧小部件?,flutter,Flutter,背景:目前我使用的是远程服务器图像查看器,我使用FutureBuilder显示图像并在图像之间切换,它工作正常,但在切换图像之间的几毫秒内会显示空白屏幕 问题:我想在加载FutureBuilder时保留旧图像小部件,或者在旧图像小部件上显示加载循环,而不是在加载时显示新的空白加载页面。或者没有FutureBuilder的任何其他解决方案(如可滚动小部件) 基本代码: class Viewer extends StatefulWidget { Viewer(this.filename, {Ke

背景:目前我使用的是远程服务器图像查看器,我使用
FutureBuilder
显示图像并在图像之间切换,它工作正常,但在切换图像之间的几毫秒内会显示空白屏幕

问题:我想在加载
FutureBuilder
时保留旧图像小部件,或者在旧图像小部件上显示加载循环,而不是在加载时显示新的空白加载页面。或者没有
FutureBuilder
的任何其他解决方案(如可滚动小部件)

基本代码:

class Viewer extends StatefulWidget {
  Viewer(this.filename, {Key key}) : super(key: key);
  final String filename;
  @override
  _ViewerState createState() {
    return _ViewerState();
  }
}

class _ViewerState extends State<Viewer> {
  int _index = 0;
  @override
  Widget build(BuildContext context) {
    return  GestureDetector(
          child: Container(
            child: showImage(context, _index),
          ),
          onPanDown: (DragDownDetails e) {
            //it will change _index to move to next image when tap down
            _index+=1;
          }
        );
  }

  Widget showImage(BuildContext context, int index) {
    return FutureBuilder<SmbHalfResult>(
      future: () async {
        //load image from remote server or from memory cache,the SmbHalfResult contain a Uint8List image.
        return SmbHalfResult();
      }(),
      builder: (BuildContext context, AsyncSnapshot<SmbHalfResult> snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.hasError) {
            return Text("Error: ${snapshot.error}");
          } else {
            //show image.
            return Image.memory(snapshot.data.result.content);
          }
        } else {
          // show loading circle,it will new a blank page,but I even want to display old image other than a blank page when loading.
          return Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}
类查看器扩展StatefulWidget{
查看器(this.filename,{Key}):超级(Key:Key);
最终字符串文件名;
@凌驾
_ViewerState createState(){
返回_ViewerState();
}
}
类_ViewerState扩展状态{
int _指数=0;
@凌驾
小部件构建(构建上下文){
返回手势检测器(
子:容器(
子项:showImage(上下文,_索引),
),
onPanDown:(Dragdown详细信息e){
//轻触时,它将更改_索引以移动到下一个图像
_指数+=1;
}
);
}
小部件showImage(BuildContext上下文,int索引){
回归未来建设者(
未来:()异步{
//从远程服务器或内存缓存加载映像时,SMBHELF结果包含Uint8List映像。
返回SmbHalfResult();
}(),
生成器:(BuildContext上下文,异步快照){
if(snapshot.connectionState==connectionState.done){
if(snapshot.hasError){
返回文本(“错误:${snapshot.Error}”);
}否则{
//显示图像。
返回Image.memory(快照、数据、结果、内容);
}
}否则{
//显示加载循环,它将显示一个新的空白页,但我甚至想在加载时显示除空白页以外的旧图像。
返回中心(子项:CircularProgressIndicator());
}
},
);
}
}
将是很好的解决方案

在小部件树中,查看器上方的小部件必须如下所示

ChangeNotifierProvider<SmbHalfResult>(
  create: (context) {
    var smbHalfResult = SmbHalfResult(); 
    smbHalfResult.fetchImage(0);
    return smbHalfResult; 
  },  
  child: Viewer(); 
)
class _ViewerState extends State<Viewer> {
  int _index = 0;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        child: Consumer<SmbHalfResult>(
          builder: (context, model) {
            if(model.image != null) return Image.memory(model.image);
            return CircularProgressIndicator(); 
          }
        ),
      ),
      onPanDown: (DragDownDetails e) {
        Provider.of<SmbHalfResult>(context, listen: false).fetchImage(); 
      }
    );
  }
}   
最后,您的实际UI必须是这样的

ChangeNotifierProvider<SmbHalfResult>(
  create: (context) {
    var smbHalfResult = SmbHalfResult(); 
    smbHalfResult.fetchImage(0);
    return smbHalfResult; 
  },  
  child: Viewer(); 
)
class _ViewerState extends State<Viewer> {
  int _index = 0;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        child: Consumer<SmbHalfResult>(
          builder: (context, model) {
            if(model.image != null) return Image.memory(model.image);
            return CircularProgressIndicator(); 
          }
        ),
      ),
      onPanDown: (DragDownDetails e) {
        Provider.of<SmbHalfResult>(context, listen: false).fetchImage(); 
      }
    );
  }
}   
class\u ViewerState扩展状态{
int _指数=0;
@凌驾
小部件构建(构建上下文){
返回手势检测器(
子:容器(
儿童:消费者(
生成器:(上下文、模型){
如果(model.image!=null)返回image.memory(model.image);
返回循环ProgressIndicator();
}
),
),
onPanDown:(Dragdown详细信息e){
Provider.of(context,listen:false).fetchImage();
}
);
}
}   
最后,我使用parameter
physics:new NeverScrollableScrollPhysics()
Preload PageController.jumpToPage(index)
,它完美地满足了我的需求,没有任何闪烁

GestureDetector(
          child: Container(
              child: PreloadPageView.builder(
            preloadPagesCount: 5,
            itemBuilder: (BuildContext context, int index) =>
                FutureImage(index, widget.filename),
            controller: preloadPageController,
            physics: new NeverScrollableScrollPhysics(),
          )),
          onPanDown: (DragDownDetails e) {
            Offset globalPosition = e.globalPosition;
            RenderBox findRenderObject = context.findRenderObject();
            Size size = findRenderObject.size;
            Area area = getArea(globalPosition, size);
            if (area == Area.lef) {
              index--;
              preloadPageController.jumpToPage(index);
            } else if (area == Area.right) {
              index++;
              preloadPageController.jumpToPage(index);
            }
          },
        )

你能添加代码吗?@PrasannaKumar谢谢你的回复kumar,我添加了一个框架代码,整个代码太复杂了。尝试将future声明为类变量并将其传递给FutureBuilder。这将阻止每次调用build函数时获取图像。加载FutureBuilder时保留旧的图像小部件。您应该只返回旧图像,而不是
CircularProgressIndicator()
@Prasanakumar我尝试了这个方法,但它仍然有一个空白的黑色页面。尝试将类<代码> SbMalMultReule<代码>更改为提供者模型,并在获取新图像时调用<代码> NoTyyListEnter()/Case>。我尝试您的方法,它最小化了空白页时间,但仍然有一点,并且我找到了类似的原生Android应用程序,它可以在没有任何空白页时间的情况下处理图像。在这种情况下似乎有些问题。稍后我将尝试滚动小部件,谢谢。