Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.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 颤振:Image.memory()以字节失败!=空';:不正确——当有数据时_Flutter_Dart - Fatal编程技术网

Flutter 颤振:Image.memory()以字节失败!=空';:不正确——当有数据时

Flutter 颤振:Image.memory()以字节失败!=空';:不正确——当有数据时,flutter,dart,Flutter,Dart,我试图根据来自后端的(base64)数据显示一个图像,但我一直收到错误bytes!=null”:不正确。 这是我的密码: class _FuncState extends State<Func> { Uint8List userIconData; void initState() { super.initState(); updateUI(); } void updateUI() async { await getUserIconDat

我试图根据来自后端的(base64)数据显示一个图像,但我一直收到错误
bytes!=null”:不正确。

这是我的密码:

class _FuncState extends State<Func> {
  Uint8List userIconData;
  
  void initState() {
    super.initState();
    updateUI();
  }

  void updateUI() async {
    await getUserIconData(1, 2, 3).then((value) => userIconData = value);
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        Container(
          child: CircleAvatar(
            backgroundImage: Image.memory(userIconData).image, // <--- problem here
            maxRadius: 20,
          ),
        ),
      ),
    );
  }
}
class\u FuncState扩展了状态{
UINT8列出用户数据;
void initState(){
super.initState();
updateUI();
}
void updateUI()异步{
等待getUserIconda(1,2,3),然后((value)=>UserIconda=value);
}
@凌驾
小部件构建(构建上下文){
返回安全区(
孩子:脚手架(
容器(
孩子:圆环星(

backgroundImage:Image.memory(usericonda.Image,//错误消息对我来说非常清楚。
usericonda
在传递给
Image.memory
构造函数时为
null


在渲染图像之前,可以使用或使用一个条件来检查
usericonda
是否为空,如果为空,则手动显示加载指示器,或者沿着这些线显示。此外,您还需要实际设置触发重新渲染的状态。不过,我会使用前者。

这非常简单;如果您查看代码,您应该能够完成这一系列操作

  • 小部件已创建。无操作。此时usericonda为空
  • initState
    被调用。异步http调用被启动。usericonda==null
  • 调用
    build
    生成发生,抛出错误。usericonda==null
  • http调用返回。usericonda已设置。usericonda==您的图像
  • 由于未调用
    setState
    ,生成函数将不会再次运行。如果您这样做,则会发生这种情况(但您之前仍然存在异常)

  • 调用
    build
    usericonda已设置。usericonda==您的图像
  • 这里的关键是理解异步调用(任何返回未来并可选地使用
    async
    await
    的调用)不要立即返回,而是在稍后的某个时间返回,您不能指望他们同时设置了您需要的内容。如果您以前尝试过使用从磁盘加载的图像执行此操作,并且成功了,那只是因为Flatter执行了一些仅在从磁盘加载是同步的情况下才可能执行的技巧

    这里有两个选项可以帮助您编写代码

    class\u FuncState扩展了状态{
    UINT8列表?用户图标数据;
    //如果您正在使用“func”小部件中的任何数据,请改用此小部件
    //在小部件发生更改的情况下初始化状态。
    //您还可以检查旧的与新的,如果没有变化
    //这需要重新加载,而不是重新加载。
    @凌驾
    void didUpdateWidget(Func oldWidget){
    super.didUpdateWidget(oldWidget);
    updateUI();
    }
    void updateUI()异步{
    等待getUserIconData(widget.role、widget.id、widget.session)。然后((值){
    //这确保了重建的发生
    设置状态(()=>usericonda=value);
    });
    }
    @凌驾
    小部件构建(构建上下文){
    返回安全区(
    孩子:脚手架(
    主体:容器(
    //如果图像已加载,则仅使用圆形化身,否则
    //显示加载指示器。
    子项:usericonda!=null?CircleAvatar(
    背景图片:Image.memory(usericonda!).Image,
    最大半径:20,
    ):CircularProgressIndicator(),
    ),
    ),
    );
    }
    }
    
    做同样事情的另一种方法是使用FutureBuilder

    class\u FuncState扩展了状态{
    //晚用并不完全安全,但我们可以相信
    //以前总是叫didUpdateWidget
    //建立这样的工作。
    未来用户数和未来数;
    @凌驾
    void didUpdateWidget(Func oldWidget){
    super.didUpdateWidget(oldWidget);
    用户图标未来=
    getUserIconda(widget.role、widget.id、widget.session);
    }
    @凌驾
    小部件构建(构建上下文){
    返回安全区(
    孩子:脚手架(
    主体:容器(
    孩子:未来建设者(
    未来:UserICondaFuture,
    生成器:(BuildContext上下文,异步快照){
    if(snapshot.hasData){
    返回圆(
    背景图片:图片。内存(快照。数据!)。图片,
    最大半径:20);
    }否则{
    返回循环ProgressIndicator();
    }
    },
    ),
    ),
    ),
    );
    }
    }
    
    请注意,加载指示器只是一个选项;实际上,我建议为您的化身(即灰色“用户”图像)设置一个硬编码的默认值,在加载图像时将其关闭


    请注意,我在这里使用了空安全代码,因为这将使此答案具有更好的使用寿命,但要切换回非空安全代码,您只需删除代码中多余的
    后期的

    非常清楚的解释,谢谢。我会尝试一下。这非常有效-我非常接近。谢谢您轻推。
    Future<Uint8List> getUserIconData(
      role,
      id,
      session,
    ) async {
      var url = Uri.https(kMobileAppAPIURL, kMobileAppAPIFolder);
      var response = await http.post(url, body: {
        'method': 'getUserProfilePic',
        'a': id.toString(),
        'b': role.toString(),
        'c': session.toString(),
      });
      if (response.statusCode == 200) {
        Map data = jsonDecode(response.body);
        return base64Decode(data['img']);
      }
      return null;
    }