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();
}
);
}
}
最后,我使用parameterphysics: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应用程序,它可以在没有任何空白页时间的情况下处理图像。在这种情况下似乎有些问题。稍后我将尝试滚动小部件,谢谢。