felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.74k stars 3.39k forks source link

fix: Animated List is not building from list in bloc state #3984

Closed becjit closed 10 months ago

becjit commented 11 months ago

Description I am facing the exact issue as described in https://stackoverflow.com/questions/68520495/why-is-animatedlist-not-building-using-list-from-bloc-state-in-flutter. Copying from the question as I am facing exact same thing

Steps To Reproduce

I am trying to create an AnimatedList using bloc pattern, but ran into some problems.

When I am setting initialItemsCount of AnimatedList to state.itemList.length, it does not build. Although when I am printing out state.itemList (that comes from ListBloc) in BlocConsumer's listener it prints out the itemList.

So, the question is why is this not working?

I tried to do the same with ListView.builder and it works fine. Am I missing something or the AnimatedList is not even supposed to work using bloc?

Here is some sample code, made it super simple for this case:

class _MyAppState extends State<MyApp> {
  final key = GlobalKey<AnimatedListState>();

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ListBloc()..add(LoadList()),
      child: MaterialApp(
        home: SafeArea(
          child: BlocConsumer<ListBloc, ListState>(
            listener: (_, state) {
              print(state.itemList);
            },
            builder: (context, state) => Scaffold(
              body: Column(
                children: [
                  Expanded(
                    child: AnimatedList(
                      key: key,
                      initialItemCount: state.itemList.length,
                      itemBuilder: (context, index, animation) {
                        return Item(
                            animation: animation,
                            index: index,
                            text: state.itemList[index],
                            onTap: () => removeItem(index, state.itemList));
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  void removeItem(int index, List<String> items) {
    final item = items.removeAt(index);

    key.currentState?.removeItem(
        index,
        (context, animation) => Item(
            animation: animation,
            index: index,
            text: items[index],
            onTap: () => removeItem(index, items)));
  }
}
class Item extends StatelessWidget {
  final Animation<double> animation;
  final int index;
  final String text;
  final VoidCallback onTap;

  const Item(
      {required this.animation,
      required this.index,
      required this.text,
      required this.onTap,
      Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScaleTransition(
      scale: animation,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: InkWell(
            onTap: onTap,
            child: Container(
              color: Colors.blue,
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(text),
              ),
            )),
      ),
    );
  }
}

Expected Behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Additional Context Add any other context about the problem here.

Trinity6264 commented 11 months ago

Try using Bloc builder, encountered the same issue, but the bug was resolved with bloc builder

Code snippet:

   Expanded(
            child: BlocBuilder<DataBloc, DataState>(
              builder: (context, state) {
                return state.when(
                  initial: () {
                    return Center(
                      child: CircularProgressIndicator.adaptive(
                        backgroundColor: context.secondaryColor,
                      ),
                    );
                  },
                  loading: () {
                    return Center(
                      child: CircularProgressIndicator.adaptive(
                        backgroundColor: context.secondaryColor,
                      ),
                    );
                  },
                  dataLoad: (_, __, transactionData, ____, ___) {
                    return CustomScrollView(
                      slivers: [
                        SliverAnimatedList(
                          key: globalKey,
                          initialItemCount: transactionData.length,
                          itemBuilder: (context, index, animation) {
                            if (index >= transactionData.length) {
                              return const SizedBox.shrink();
                            }
                            final model = transactionData[index];
                            return SlideTransition(
                              position: Tween<Offset>(
                                begin: const Offset(0, 1),
                                end: Offset.zero,
                              ).animate(
                                CurvedAnimation(
                                  parent: animation,
                                  curve: Curves.linear,
                                ),
                              ),
                              child: FadeTransition(
                                opacity: Tween<double>(begin: 0, end: 1)
                                    .animate(animation),
                                alwaysIncludeSemantics: true,
                                child: TransactionCard(transactionModel: model),
                              ),
                            );
                          },
                        ),
                      ],
                    );

With the above code works

becjit commented 11 months ago

@Trinity6264 hi thanks! But bloconsumer already has blocbuilder. In any case I will give your code a try. Could you also check if it is working with AnimatedlIst instead of SliverAnimatedList

tenhobi commented 10 months ago

Hey, so what is the status? Did you resolve your issue?

felangel commented 10 months ago

Closing for now since there aren't any actionable next steps. Feel free to provide additional context if this is still an issue and we're happy to help 👍

becjit commented 10 months ago

@felangel @tenhobi Nope this is not resolved. Could you please keep it open