Flutter rerun initState function of inner StatefulWidget

0

I have one outer StatefulWidget and one inner StatefulWidget. When I use setState() on the outer Widget, the inner Widget's build function gets rerun. Is there a way to also trigger the initState method? This is the inner Widget:

class _Image extends StatefulWidget {

  final String _imageId;

  _Image(this._imageId);

  @override
  State createState() => new _ImageState();

}
class _ImageState extends State<_Image> {

  ImageResponse image;

  @override
  void initState() {
    super.initState();

    // fetch image using the provided imageId
    fetchImage(widget._imageId).then((ImageResponse imageResponse) {
      setState(() {
        image = imageResponse;
      });
    });
  }


  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 350.0,
      height: 350.0,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.all(Radius.circular(8)),
        color: Color(0xffFFFFFF),
        image: image != null ? DecorationImage(
          fit: BoxFit.cover,
          image: NetworkImage(image.downloadURL)
        ) : null,
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.25),
            spreadRadius: 0,
            blurRadius: 4,
            offset: Offset(0, 4)
          )
        ]
      ),
    );
  }

} 

A very simple Widget as you can see. You can provide an imageId and the Widget will fetch the data of that image and will display it. Now I want that when the outer Widget get's updated, not only the build function get's rerun but also the initState function, so that the new image-data for that imageId can be fetched.

android
ios
flutter
dart
flutter-layout
asked on Stack Overflow Sep 30, 2020 by Paul Hanneforth

1 Answer

1

You can use a FutureBuilder to show the view with an image loader until the image is loaded. Each time you launch this widget, it will call for the image.

class _Image extends StatefulWidget {

  final String _imageId;

  _Image(this._imageId);

  @override
  State createState() => new _ImageState();

}
class _ImageState extends State<_Image> {

  ImageResponse image;

  @override
  void initState() {
    super.initState();

  }
    
    Future<ImageResponse> loadImage() async {
        ImageResponse res = await fetchImage(widget._imageId);
        return res;
    }


  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
            future: loadImage(),
            builder: (context, snapshot) {
                if (snapsnot.connectState==ConnectionState.done) {
                return new Container(
                    width: 350.0,
                    height: 350.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.all(Radius.circular(8)),
                        color: Color(0xffFFFFFF),
                        image: image != null ? DecorationImage(
                            fit: BoxFit.cover,
                            image: NetworkImage(snapshot.data.downloadURL)
                        ) : null,
                        boxShadow: [
                            BoxShadow(
                                color: Colors.grey.withOpacity(0.25),
                                spreadRadius: 0,
                                blurRadius: 4,
                                offset: Offset(0, 4)
                            )
                        ]
                    ),
                );
                } else {
                    // paint whatever you want to the screen while the image loads. I'm using an empty container as an example
                    return Container();
                }
            }
        )
        
        
  }

} 
answered on Stack Overflow Sep 30, 2020 by daddygames • edited Oct 4, 2020 by Paul Hanneforth

User contributions licensed under CC BY-SA 3.0