Search code examples
flutterflutter-sliverflutter-getx

SliverList and Getx StateMixin support


I'm struggling trying to make a GetxController work with a SliverList. In particular, my controller returns the view state with StateMixin from Getx library.

class ItinerariesByCreatorPageController extends GetxController
    with StateMixin<Pair<Creator, List<Itinerary>>> {
  ItinerariesByCreatorPageController(this._interactor);

  final ItinerariesInteractor _interactor;

  void getCreatorPage(String creatorSlug, String language) {
    _interactor
        .getItinerariesByCreatorSlug(creatorSlug, language)
        .then((value) => change(value, status: RxStatus.success()))
        .onError<String>((error, stackTrace) =>
            change(null, status: RxStatus.error(error.toString())));
  }
}

On the view side, I'm using obx extension to observe the controller state and a SliverList to display data. Unfortunately, SliverList delegate SliverChildBuilderDelegate needs to provide list childCount in its constructor, but the child count comes asynchronously from the controller and I can't find a way on the Getx documentation to return the child count in a reactive way. Is there any way to make SliverList and Getx work together?

Widget _getItinerariesList() {
    return SliverList(
        delegate: SliverChildBuilderDelegate(
            (context, index) => _controller.obx((data) {
                  if (index == 0) {
                    return CreatorInfoWidget(
                      creator: data.first,
                      imageWidget: CreatorImageWidget(
                        imageUrl: data.first.avatars.first,
                      ),
                    );
                  } else if (index == 1) {
                    return MainItineraryWidget(
                        creator: data.first, itinerary: data.second[index - 1]);
                  } else {
                    return SecondaryItineraryWidget(
                        creator: data.first, itinerary: data.second[index - 1]);
                  }
                }),
            childCount: 5 // use a dynamic child count here, coming from the controller));
  }

Solution

  • You can move up controller.obx above the SliverList

    Widget _getItinerariesList() {
    return _controller.obx((data) {
      return SliverList(
            delegate: SliverChildBuilderDelegate(
            (context, index){
                  if (index == 0) {
                    return CreatorInfoWidget(
                      creator: data.first,
                      imageWidget: CreatorImageWidget(
                        imageUrl: data.first.avatars.first,
                      ),
                    );
                  } else if (index == 1) {
                    return MainItineraryWidget(
                        creator: data.first, itinerary: data.second[index - 1]);
                  } else {
                    return SecondaryItineraryWidget(
                        creator: data.first, itinerary: data.second[index - 1]);
                  }
                }),
            childCount: data.yourCountVariable // use a dynamic child count here, coming from the controller));
       }
    }