flutter 中的一个控制器两个小部件

发布于 2025-01-14 20:16:50 字数 3884 浏览 0 评论 0原文

是否有任何选项可以为两个小部件保留一个控制器?我有 3 个按钮来更改视图,其中两个使用相同的分页控制器,一切正常,直到切换到第三个视图。然后,返回第一或第二视图后,控制器停止工作。

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仅根据视图参数改变列表的显示,但使用相同的控制器。

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();
          },
        ),
      ),
    );
  }
}

获取方法

  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;
    }
  }

从view3返回到view12后错误描述:

从view3返回view12后的错误描述

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月朦胧 2025-01-21 20:16:50

像这样使用它,

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

Use it like this,

 final PagingController<int, Item> _pagingController =
  PagingController(firstPageKey: 1);
叹梦 2025-01-21 20:16:50
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;
}

}
方法

像这样改变你的获取

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文