在构造函数抖动中调用SetState()

时间:2020-06-04 14:40:00

标签: flutter

我试图创建一个Gesture_detector,当按下一个图标时,该Gesture_detector会调用将来的函数。从下面的代码中调用包含这个action_detector的窗口小部件生成器。

`class MyHomePageState extends State<MyHomePage> {
  File contentimage, style_image;


  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Neural Style transfer'),
        ),
        body: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
             //I am calling the builder from here.
            imagepreview_state().build_imagepreview(context, contentimage,'Content Image'),
            imagepreview_state().build_imagepreview(context, style_image,'Style Image')
          ],
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: (){
           // image = await getImage_gallery(image);
          },
          tooltip: 'Pick Image',
          child: Icon(Icons.add_a_photo),
        ),
      ),
    );
  }

}
`

以下包含构建器。

    class imagepreview extends StatefulWidget {
  imagepreview_state createState() => imagepreview_state();
}

class imagepreview_state extends State<imagepreview> {
  noSuchMethod(Invocation i) => super.noSuchMethod(i);

  File image;
  final picker = ImagePicker();

  //These future functions get the images from the respective sources when an icon is pressed

  Future getImage_gallery(File _image) async {
    final pickedFile = await picker.getImage(source: ImageSource.gallery);
    _image = File(pickedFile.path);
    setState(() {
      _image = File(pickedFile.path);
    });
    return _image;
  }

  Future<File> getImage_camera(File _image) async {
    final pickedFile = await picker.getImage(source: ImageSource.camera);

    setState(() {
      _image = File(pickedFile.path);
    });

    return _image;
  }

  Widget build_imagepreview(BuildContext context, File image, String title) {
    return (Container(
        padding: EdgeInsets.only(top: 30),
        child: Column(children: <Widget>[
          GestureDetector(
            onTap: () {
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => MyDetailPage(image)));
            },
            child: Container(
              height: 150,
              width: 150,
              child: image == null
                  ? Text('No image selected.')
                  : Column(children: <Widget>[
                      Text(title),
                      SizedBox(
                        height: 5,
                      ),
                      Container(
                        height: 120.0,
                        width: 120.0,
                        decoration: BoxDecoration(
                          image: DecorationImage(
                            image: FileImage(image),
                            fit: BoxFit.cover,
                          ),
                          shape: BoxShape.rectangle,
                        ),
                      )
                    ]),
            ),
          ),
          Container(
            padding: EdgeInsets.all(10),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                GestureDetector(
                  onTap: () async{
                    image = await getImage_camera(image);
                  },
                  child: Icon(
                    Icons.camera_alt,
                    color: Colors.blue,
                    size: 40.0,
                    semanticLabel: 'Text to announce in accessibility modes',
                  ),
                ),
                SizedBox(
                  width: 10,
                ),
                GestureDetector(
                  onTap: () async{
                    image = await getImage_gallery(image);

                  },
                  child: Icon(
                    Icons.settings_system_daydream,
                    color: Colors.blue,
                    size: 40.0,
                  ),
                ),
              ],
            ),
          )
        ])));
  }
}

问题:

有没有什么方法可以刷新构建而无需调用setstate()并在按下图标时做出反应?

2 个答案:

答案 0 :(得分:0)

我认为您希望避免在此处调用setState()的原因是您决定使用自己的构建器函数。我建议将build_imagepreview替换为build的{​​{1}}函数,以便您可以从imagepreview_state调用setState()。通过为GestureDetector创建构造函数,您仍然可以通过content_image的{​​{1}}属性传递style_imageimage。此外,您可以将imagepreview_state从异步功能中移出。

答案 1 :(得分:0)

您将需要使用setState()再次调用构建函数。问题是您没有使用继承的Build()函数。我猜这是因为您要将参数传递到imagepreview小部件中。解决此问题的一种方法是将参数作为类属性直接传递到小部件中,而不传递给自定义构建函数。附带说明,从技术上讲,这是正确构建窗口小部件树的方法,并且您不应在要创建的状态内调用方法。

然后您可以创建窗口小部件:

imagepreview(contentimage,'Content Image'),
imagepreview_(style_image,'Style Image')

然后您可以使用widget.propertyName在子级中访问这些文件。

现在确保使用

  @override
  Widget build(BuildContext context) {}

方法,然后setState()应该起作用。

如果您随后需要更新父窗口小部件中的所有内容,则还可以传入一个函数,包括在父窗口中调用setState()的函数。

希望这会有所帮助!