'I am trying to use keys to preserve the state of the widgets and remove the blinking effect when setState is called

I am trying to remove the blinking/flashing effect after the widgets are rebuild. I read about keys, but it's not working, I added a unique key to every GridView builder element as you see in the code below. Now when I resize, the widgets are rebuilt because the setState function is called but I can not preserve their state.

  void addOutfitPlannerDialog(BuildContext context) async{
    await showGeneralDialog(
        barrierColor: Colors.black.withOpacity(0.5),
        transitionBuilder: (context, a1, a2, widget) {
        return SafeArea(
          child: Transform.scale(
          scale: a1.value,
          child: Opacity(
          opacity: a1.value,
            child: AlertDialog(
            actionsPadding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
            contentPadding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
            titlePadding: const EdgeInsets.fromLTRB(20, 20, 20, 0),
            buttonPadding: const EdgeInsets.all(0),
            title: _getBackAndSaveButtons(context),
            backgroundColor: Colors.white,
            insetPadding: const EdgeInsets.all(0),
            content:  StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return SizedBox(
              width: 100.w,
              height: 100.h,
              child: Stack(
                children: [
                  Positioned(
                    top: 0,
                    child:
                    Container(
                      width: 100.w,
                      height: 82.h,
                      color: const Color(0xff393432),
                      child: FittedBox(
                        fit: BoxFit.fill,
                        child: Container(
                          width: 100.w,
                          height: 100.h,
                          margin: EdgeInsets.fromLTRB(45, 10, 45, 15.h),
                          child: Screenshot(
                            controller: screenshotController,
                            child: Container(
                              color: Colors.white,
                              child: Stack(
                                children: stackChildren,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: 0,
                    child: Container(
                      height: heightBottomOutfitPlanner,
                      decoration: const BoxDecoration(
                        color: Colors.white,
                        border: Border(
                          top: BorderSide( //                    <--- top side
                            color: Colors.grey,
                            width: 1.0,
                          ),
                        ),
                      ),
                      width: 100.w,
                      child: Column(
                        children: [
                          SizedBox(
                            width: 100.w,
                            height: 8.h,
                            child: Row(
                              children: [
                                Expanded(
                                  flex: 7,
                                  child: ListView.builder(
                                      scrollDirection: Axis.horizontal,
                                      itemCount: outfitPlanerOrganizerEntriesList
                                          .length,
                                      itemBuilder: (BuildContext context,
                                          int index) {
                                        return InkWell(
                                          onTap: () {
                                            getOutfitPlannerTabTappedImages(
                                                outfitPlanerOrganizerEntriesList[index],
                                                setState);
                                          },
                                          child: Container(
                                            padding: const EdgeInsets.fromLTRB(
                                                30, 0, 30, 0),
                                            decoration: (outfitPlanerOrganizerEntriesList[index] ==
                                                myOutfitPlannerTabTappedImages[0]
                                                    .closetOrganizer) ||
                                                (outfitPlanerOrganizerEntriesList[index] ==
                                                    "To Buy" &&
                                                    myOutfitPlannerTabTappedImages[0]
                                                        .closetOrganizer ==
                                                        null)
                                                ? const BoxDecoration(
                                              border: Border(
                                                bottom: BorderSide( //                    <--- top side
                                                  color: Color(0xffE4BCB4),
                                                  width: 3.0,
                                                ),
                                              ),
                                            )
                                                : null,
                                            child: Center(child: Text(
                                                outfitPlanerOrganizerEntriesList[index],
                                                style: TextStyle(
                                                  fontSize: SizerUtil
                                                      .deviceType ==
                                                      DeviceType.mobile
                                                      ? 16
                                                      : 25,
                                                ))),
                                          ),
                                        );
                                      }
                                  ),
                                ),
                                const SizedBox(width: 30),
                                Expanded(
                                  flex: 1,
                                  child: Container(
                                      decoration: const BoxDecoration(
                                        border: Border(
                                          left: BorderSide( //                    <--- top side
                                            color: Colors.black,
                                            width: 1.0,
                                          ),
                                        ),
                                      ),
                                      child: GestureDetector(
                                        onPanStart: (details) =>
                                            _handleDrag(details, setState),
                                        onPanUpdate: (details) =>
                                            _handleUpdate(details, setState),
                                        child: Icon(Icons.drag_indicator,
                                          size: SizerUtil.deviceType ==
                                              DeviceType.mobile ? 35 : 45,
                                        ),
                                      )

                                  ),
                                ),
                              ],
                            ),
                          ),
                          const SizedBox(height: 5),
                          !isLoadingOutfitPlannerTabTappedImages ? Container(
                            width: 100.w,
                            margin: const EdgeInsets.fromLTRB(5, 0, 5, 0),
                            height: heightBottomOutfitPlanner - 10.h,
                            child: GridView.builder(
                                physics: const ScrollPhysics(),
                                shrinkWrap: true,
                                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                                  crossAxisSpacing: 5,
                                  mainAxisSpacing: 5,
                                  maxCrossAxisExtent: SizeConfig.screenWidth! /
                                      4,),
                                itemCount: myOutfitPlannerTabTappedImages
                                    .length,
                                itemBuilder: (BuildContext ctx, index) {
                                  return InkWell(
                                    key: Key(index.toString()),
                                    onTap: () {
                                      try {
                                        removeBackground(ctx, setState, CleverCloset.dataFromBase64String(myOutfitPlannerTabTappedImages[index].getImage!));
                                      }
                                      catch (e) {
                                        stackChildren.add(MoveableStackItem(CleverCloset.imageFromBase64String(myOutfitPlannerTabTappedImages[index].getImage!).image));
                                      }
                                      },
                                    child: Container(
                                      decoration: const BoxDecoration(
                                          borderRadius: BorderRadius.all(
                                              Radius.circular(20))
                                      ),
                                      width: SizeConfig.screenWidth! / 4,
                                      height: SizeConfig.screenWidth! / 4,
                                      child: FittedBox(
                                        child:
                                        FadeInImage(
                                          placeholder: const AssetImage(
                                              'assets/placeholder.gif'),
                                          image: CleverCloset
                                              .imageFromBase64String(
                                              myOutfitPlannerTabTappedImages[index]
                                                  .getImage!)
                                              .image,
                                          fit: BoxFit.fill,
                                        ),
                                        fit: BoxFit.fill,
                                      ),
                                    ),
                                  );
                                }
                            ),
                          ) : Container(),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            );
          }
            )
          ),
            ),
          ),
        );
    },
    transitionDuration: const Duration(milliseconds: 100),
    barrierDismissible: false,
    barrierLabel: '',
    context: context,
    pageBuilder: (context, animation1, animation2) {return Container();}
    );
  }

output gif



Solution 1:[1]

You can add the below logic to your code. It basically gets executed when the widget has build.

void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) => function(context));
}

And now you can implement the function(context) to do what you need to do after the build.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ankit Kumar Maurya