TatsuUkraine / flutter_sticky_infinite_list

Multi directional infinite list with Sticky headers for Flutter applications
BSD 2-Clause "Simplified" License
341 stars 31 forks source link

Rebuilding all InfiniteListItem on setState #45

Closed sh00le closed 3 years ago

sh00le commented 3 years ago

Describe the bug This can be bug with flutter framework, but here is what is going on. When Infinitive list is set to infinitive bidirectional and scrolling to "positive" index side - after setState - all InfiniteListItems are built. With same parameters and scrolling to "negative" index side - after setState - only visible InfiniteListItems are build.

To Reproduce Steps to reproduce the behavior:

  1. Scroll down (positive index side)
  2. After scroll ended - setState is called
  3. InfiniteListItems are built starting with index -1 (check log - debugPrint added)
  4. Scroll up (negative index side)
  5. After scroll ended - setState is called
  6. Only visible InfiniteListItems are built (check log - debugPrint added)

Expected behavior setState should rebuild only "visible" InfiniteListItems (inside viewport) on both side the same way.

Code example

import 'package:sticky_infinite_list/sticky_infinite_list.dart';
import 'package:flutter/material.dart';

class StickyInfiniteList extends StatefulWidget {
  @override
  StickyInfiniteListState createState() => StickyInfiniteListState();
}

class StickyInfiniteListState extends State<StickyInfiniteList> {

  @override
  Widget build(BuildContext context) {
    return  NotificationListener<ScrollNotification>(
        onNotification: (ScrollNotification scrollInfo) {
          if (scrollInfo is ScrollEndNotification) {
            setState(() {
              debugPrint('setState');
            });
          }
          return true;
        },
      child: InfiniteList(
          controller: ScrollController(),
          direction: InfiniteListDirection.multi,
          builder: (BuildContext context, int index) {
            return InfiniteListItem(
              contentBuilder: (BuildContext context) {
                debugPrint('builder $index');
                return Container(
                  height: 300,
                  child: Text(
                    "Content $index",
                    style: TextStyle(
                      color: Colors.white,
                    ),
                  ),
                  color: Colors.blueAccent,
                );
              },
            );
          }
      ),
    );
  }
}

Environment (please complete the following information): Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 1.22.3, on Microsoft Windows [Version 10.0.18363.1139], locale hr-HR) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2) [!] Android Studio (version 4.1.0) X Flutter plugin not installed; this adds Flutter specific functionality. X Dart plugin not installed; this adds Dart specific functionality. [√] Connected device (1 available)

TatsuUkraine commented 3 years ago

thanks for the issue.

It seems that it's a flutter default behavior in order to identify what sliver should be rendered since the multi-directional infinite list is actually based on 2 slivers, where 1 of them is a center sliver item, which is a built-in approach to build such layout

I will try your example as soon as I get time, but at this point, I doubt that it's something related to my package)

sh00le commented 3 years ago

I know that this can be flutter related thing. But I'm confused why "negative" side doesn't have this issue. Negative side also have multi-directional infinite list, but rendering only "visible" slivers.

TatsuUkraine commented 3 years ago

It's probably related to the fact, that negative sliver builder is a first item in the sliver list of custom scroll view widget

TatsuUkraine commented 3 years ago

In any case, I will try to dig into flutter sources to find out what is the source of such behavior and if it's related to my particular implementation of the infinite list

TatsuUkraine commented 3 years ago

ok, so I found the issue. I didn't get from the first time what kind of issue is it actually) sorry that mislead you. I was thinking that the issue, which you described, is that it renders first item of the list each time you do setState

TatsuUkraine commented 3 years ago

so yes, I can confirm that it re-renders all positive list, starting from the first item after each setState

sh00le commented 3 years ago

Cool, I have tested fix and it's seem to be working as intended.

TatsuUkraine commented 3 years ago

awesome, I will publish a new version in a few minutes

TatsuUkraine commented 3 years ago

a new version with this fix is available in pub.dev

sh00le commented 3 years ago

Thank you.