flutterdartsetstateimagepicker

setState of a single widget inside a statelesswidget


I do have a StatelessWidget name MyImagesPage and it contains various StatelessWidgets and I do have a one particular widget that I want to update and I've tried using StatefulBuilder however it does not work. Here is the snippet of my code.

class MyImagesPage extends StatelessWidget {
  const MyImagesPage({super.key});

  @override
  Widget build(BuildContext context) {
    return StatefulBuilder(
      builder: (context, setState) {
        return CarouselSlider(
          carouselController: controller,
          options: CarouselOptions(
              height: MediaQuery.of(context).size.height,
              viewportFraction: 1.0,
              enlargeCenterPage: true,
              aspectRatio: 2.0,
              pageSnapping: true,
              enableInfiniteScroll: false,
              onPageChanged: (index, reason) {
                setState(() {
                  currentSlide = index;
                  print("currentSlide: $currentSlide");
                });
              }
              // autoPlay: false,
              ),
          items: validatedImageList
              .map((item) => Container(
                  decoration: const BoxDecoration(
                    borderRadius: BorderRadius.all(
                      Radius.circular(10),
                    ),
                  ),
                  child: ClipRRect(
                    borderRadius: const BorderRadius.all(
                      Radius.circular(10),
                    ),
                    child: Image.file(
                      File(item.path),
                      fit: BoxFit.cover,
                      height: MediaQuery.of(context).size.height,
                    ),
                  )))
              .toList(),
        );
      },
    );
  }
}

and I do have a button that triggers the image picking event

ElevatedButton(
     child: const Text('Select Image'),
     onPressed: () {
        FunctionHelper.selectImagesFunction(
           context,
           imageFileList,
           validatedImageList,
           invalidFileSizeImageList,
           imagePicker,
           stateSet,
           );
           Navigator.of(context).pop();
   });
and here is the code of my ``FunctionHelper`` class.
class FunctionHelper {
  static selectImagesFunction(BuildContext context, List<XFile> imageFileList, List<XFile> validatedImageList, List<XFile> invalidFileSizeImageList,
      ImagePicker imagePicker) async {
    final List<XFile> selectedImages = await imagePicker.pickMultiImage(
      imageQuality: 60,
    );
    if (selectedImages.isNotEmpty) {
      imageFileList.addAll(selectedImages);
    }
    if (imageFileList.length >= 7) {
      // ignore: use_build_context_synchronously
      Utils.animatedSnackbar(
          context: context,
          mobileSnackBarPosition: MobileSnackBarPosition.top,
          snackBarTitle: "Ops! You selected more than 6",
          snackBarType: AnimatedSnackBarType.error);
    } else {
      for (var x in imageFileList) {
        const maxFileSizeInBytes = 3 * 1048576;
        var imagePath = await x.readAsBytes();
        var fileSize = imagePath.length; // filesize of every imaages looped in the list.
        if (x.path.endsWith(".jpg") || x.path.endsWith(".png") || x.path.endsWith(".jpeg") || x.path.endsWith(".gif")) {
          print("allowed: .jpg / .jpeg / .png / .gif ");
          if (fileSize <= maxFileSizeInBytes) {
            print("image name: ${x.name} and image size: ${filesize(fileSize)} and maxFileSize: ${filesize(maxFileSizeInBytes)}");
            validatedImageList.add(x);
          } else {
            print("INVALID! image name: ${x.name} and image size: ${filesize(fileSize)} and maxFileSize: ${filesize(maxFileSizeInBytes)}");
            invalidFileSizeImageList.add(x);
          }
        } else {
          print("not allowed with no: .jpg / .jpeg / .png / .gif ");
        }
      }
    }
    
  }

I am contemplating whether to just extract the codes under the StatefulBuilder and just create a StatefulWidget for that single widget for viewing the image.


Solution

  • Your approach is to build your whole screen. So, Simply convert your stateless widget to a stateful widget. But it's not good practice for state management

    class MyImagesPage extends StatefulWidget {
      const MyImagesPage({super.key});
    
      @override
      State<MyImagesPage> createState() => _MyImagesPageState();
    }
    
    class _MyImagesPageState extends State<MyImagesPage> {
      @override
      Widget build(BuildContext context) {
        return CarouselSlider(
              carouselController: controller,
              options: CarouselOptions(
                  height: MediaQuery.of(context).size.height,
                  viewportFraction: 1.0,
                  enlargeCenterPage: true,
                  aspectRatio: 2.0,
                  pageSnapping: true,
                  enableInfiniteScroll: false,
                  onPageChanged: (index, reason) {
                    setState(() {
                      currentSlide = index;
                      print("currentSlide: $currentSlide");
                    });
                  }
                  // autoPlay: false,
                  ),
              items: validatedImageList
                  .map((item) => Container(
                      decoration: const BoxDecoration(
                        borderRadius: BorderRadius.all(
                          Radius.circular(10),
                        ),
                      ),
                      child: ClipRRect(
                        borderRadius: const BorderRadius.all(
                          Radius.circular(10),
                        ),
                        child: Image.file(
                          File(item.path),
                          fit: BoxFit.cover,
                          height: MediaQuery.of(context).size.height,
                        ),
                      )))
                  .toList(),
            );
       
      }
    }