使用 Flutter、Ferry、Graphql 进行分页?

问题描述 投票:0回答:1

我已连接 graphql,并且相关集合包含大约 2000 个文档。我想做的只是一次加载 25 个。如果我执行查询来获取完整列表,则需要 5-10 秒,所以我需要的是它一次只请求 25 秒。 我让它工作,所以它将加载 X 数量的文档并将它们显示在列表中。我不知道如何使分页工作。我已经阅读了文档 100 遍,但我无法理解它。这是渡轮的分页文档https://ferrygraphql.com/docs/pagination

我对 flutter 和 dart 相当陌生,所以这里的任何帮助将不胜感激。谢谢你。

这是我的代码。目前,这仅显示前 25 个文档,没有其他内容。

class DisplayPartnerOrganistions extends StatefulWidget {
  @override
  _DisplayPartnerOrganistionsState createState() =>
      _DisplayPartnerOrganistionsState();
}

class _DisplayPartnerOrganistionsState
    extends State<DisplayPartnerOrganistions> {
  var offset = 0;
  final client = GetIt.I<Client>();
  late GFetchPartnerOrganisationsReq fetchPartnerOrganisationsReq;

  @override
  void initState() {
    super.initState();
    fetchPartnerOrganisationsReq = GFetchPartnerOrganisationsReq(
      (b) => b
        ..vars.offset = offset
        ..vars.limit = 25,
    );
  }

  Widget _buildList(partners) {
    return ListView.builder(
        padding: const EdgeInsets.all(16.0),
        itemBuilder: (context, item) {
          return _buildRow(partners[item]);
        });
  }

  Widget _buildRow(partnerOrganisation) {
    return ListTile(
      title: Text(partnerOrganisation.toString()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Partner Organisations'),
      ),
      body: Operation<GFetchPartnerOrganisationsData,
              GFetchPartnerOrganisationsVars>(
          client: client,
          operationRequest: fetchPartnerOrganisationsReq,
          builder: (context, response, error) {
            if (response!.loading) {
              return const Center(child: CircularProgressIndicator());
            }
            final partners = response.data?.partnerOrganizations;
            return _buildList(partners);
          }),
    );
  }
}

我尝试了不同的事情大约 12 个小时,但没有任何意义。我是否使用了错误的小部件或其他东西?

flutter dart graphql pagination ferry
1个回答
-1
投票

您需要创建一个

requestId
,以便渡轮将对不同页面的不同请求视为相同:

final fetchPartnerOrganisationsReq = GFetchPartnerOrganisationsReq((req) =>
  req
    ..requestId = 'myRequestId'
    ..vars.offset = 0
    ..vars.limit = 25,
);

如果您不这样做,Ferry 会根据您的请求类型和请求的变量创建一个 id,该 id 对于不同的页面会有所不同(

offset
不会相同)。

然后,当您需要加载更多数据时,您可以使用不同的变量重建请求(

offset
)。重建它将使您能够保留您最初指定的相同
requestId

final newRequest = fetchPartnerOrganisationsReq.rebuild((request) =>
  // `requestId` is still `'myRequestId'`
  request..vars.offset = fetchPartnerOrganisationsReq.vars.offset + 25 // <- You update the offset here
  request..updateResult = (previous, result) {
    // This tells ferry what to do when you get the result from the new query.
    // Since it is using the same id as the initial one (with `offset = 0`), by default it will override the result.
    // Here we can tell ferry how to keep both.
    // `previous` is what you already received in the previous query (the previous page).
    // `result` is the new page you get.
    if (previous == null) return result; // If we didn't have a previous page yet, we just use what we got with the new query.
    return previous!.rebuild((previous) =>
      previous.partnerOrganizations.addAll(result!.partnerOrganizations), // We concatenate the lists of the previous pages and the new one.
    );
  },
);

client.requestController.add(newRequest); // This line is important

您什么时候创建新请求?

可能是当您到达列表末尾时。您可以通过将

ScrollController()
与侦听器一起使用来了解这一点。您可以通过
_scrollController.position.extentAfter == 0
) 知道您已到达列表末尾。

© www.soinside.com 2019 - 2024. All rights reserved.