Home > Software design >  One controller two widgets in flutter
One controller two widgets in flutter

Time:03-18

is there any option to keep one controller for two widgets? I have 3 buttons to change view, two of them use the same paging controller, everything works fine until it switches to the third view. Then, after back to the first or second view, the controller stop working.

class ViewsScreen extends StatefulWidget {
  const ViewsScreen({Key? key}) : super(key: key);

  @override
  State<ViewsScreen> createState() => _ViewsScreenState();
}

class _ViewsScreenState extends State<ViewsScreen> {
  int _view = 1;
  final _pagingController = PagingController<int, Item>(
    firstPageKey: 1,
  );

  @override
  void dispose() {
    _pagingController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Container(
            width: double.infinity,
            height: 40,
            child: Row(
              children: [
                _pageButton(Icons.one_k, 'view1', 1),
                _pageButton(Icons.two_k, 'view2', 2),
                _pageButton(Icons.three_k, 'view3', 3),
              ],
            ),
          ),
          Expanded(
              child: _view == 1
                  ? View12(
                      view: 1,
                      controller: _pagingController,
                    )
                  : _view == 2
                      ? View12(
                          view: 2,
                          controller: _pagingController,
                        )
                      : View3()),
        ],
      ),
    );
  }

  Widget _pageButton(IconData icon, String name, int view) {
    return Expanded(
      child: InkWell(
        onTap: () {
          setState(() {
            _view = view;
          });
        },
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(icon),
            Text(name),
          ],
        ),
      ),
    );
  }
}

View12 only changes the display of the list depending on the view parameter, but uses the same controller.

class View12 extends StatefulWidget {
  final int view;
  final PagingController<int, Item> controller;
  const View12(
      {Key? key, required this.view, required this.controller})
      : super(key: key);

  @override
  _View12ViewState createState() => _View12ViewState();
}

class _View12ViewState extends State<View12> {
  @override
  void initState() {
    widget.controller.addPageRequestListener((pageKey) {
      //fetching data from service
      context.read<ViewModel>().fetchPage(pageKey, widget.controller);
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () => Future.sync(
        () => widget.controller.refresh(),
      ),
      child: PagedListView.separated(
        pagingController: widget.controller,
        separatorBuilder: (context, index) =>
            Container(height: 1, color: Colors.black),
        builderDelegate: PagedChildBuilderDelegate<Item>(
          itemBuilder: (context, item, index) {
            if (widget.view == 1)
              return ItemGallery(
                item: item,
              );
            if (widget.view == 2)
              return ItemList(
                item: item,
              );
            return Container();
          },
        ),
      ),
    );
  }
}

Fetching method

  Future<void> fetchPage(
      int pageKey, PagingController<int, Offer> controller) async {
    try {
      final newItems = await loadData(pageKey);
      if (isLastPage) {
        controller.appendLastPage(newItems);
      } else {
        final nextPageKey = pageKey   1;
        controller.appendPage(newItems, nextPageKey);
      }
    } catch (error) {
      controller.error = error;
    }
  }

Error description after returning from view3 to view12:

error description after returning from view3 to view12

CodePudding user response:

Use it like this,

 final PagingController<int, Item> _pagingController =
  PagingController(firstPageKey: 1);

CodePudding user response:

Future<void> _fetchPage(int pageKey) async {
try {
  const _pageSize = 3;
  final newItems =  await loadData(pageKey);
  final isLastPage = newItems.length < _pageSize;
  if (isLastPage) {
    _pagingController.appendLastPage(newItems);
  } else {
    final nextPageKey = pageKey   newItems.length;
    _pagingController.appendPage(newItems, nextPageKey);
  }
} catch (error) {
  _pagingController.error = error;
}

} }

change your fetching method like this

  • Related