algolia / algoliasearch-helper-flutter

⚡️ Building block to create instant-search applications with Flutter
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/flutter/
Other
21 stars 14 forks source link

There's an issue with fetching data for the next page. #117

Closed Patrick386 closed 7 months ago

Patrick386 commented 7 months ago

I've written a small sample code for testing as follows. The issue is that it's not fetching the next page. Can you help identify and fix any problems in the code?

class DemoView extends StatefulWidget {
  const DemoView({super.key});

  @override
  State<DemoView> createState() => _DemoViewState();
}

class _DemoViewState extends State<DemoView> {
  final PagingController<int, DemoData> _pagingController =
      PagingController<int, DemoData>(firstPageKey: 0);

  late HitsSearcher _hitsSearcher;
  Stream<_HitsPage> get _searchPage =>
      _hitsSearcher.responses.map(_HitsPage.fromResponse);

  @override
  void initState() {
    _hitsSearcher = HitsSearcher(
      applicationID: Env.algoliaApplicationID,
      apiKey: Env.algoliaApiKey, // adminKey search-only demo key
      indexName: AlgoliaCredentials.demoEcommerceIndex, // demo_ecommerce
    );

    _searchPage.listen((_HitsPage page) {
      if (page.pageKey == 0) {
        _pagingController.refresh();
      }
      logger.info('nextPageKey:${page.nextPageKey} / Page item length:${page.items.length}'); // 1 / 20
      _pagingController.appendPage(page.items, page.nextPageKey);
    }).onError((error) => _pagingController.error = error);

    _pagingController.addStatusListener((status) {
      // status:PagingStatus.ongoing
      logger.info('status:${status.toString()}');
    });
    super.initState();
  }
  @override
  void dispose() {
    _pagingController.dispose();
    _hitsSearcher.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
     appBar: AppBar(),

      body: PagedListView<int, DemoData>(
          pagingController: _pagingController,
          builderDelegate: PagedChildBuilderDelegate<DemoData>(
              noItemsFoundIndicatorBuilder: (_) => const Center(
                    child: Text('No results found')),
              itemBuilder: (_, DemoData item, __) => Container(
                    color: Colors.white,
                    height: 80,
                    padding: const EdgeInsets.all(8),
                    child: Row(
                      children: [
                        if (item.image != null)
                          SizedBox(
                              width: 50, child: Image.network(item.image!)),
                        const SizedBox(width: 20),
                        Expanded(child: Text('${item.name}'))
                      ],
                    ),
                  ))),
    );

  }
}

class _HitsPage {
  const _HitsPage(this.items, this.pageKey, this.nextPageKey);

  final List<DemoData> items;
  final int pageKey;
  final int? nextPageKey;

  factory _HitsPage.fromResponse(SearchResponse response) {
    final items = response.hits.map(DemoData.fromJson).toList();
    final isLastPage = response.page >= response.nbPages;
    final nextPageKey = isLastPage ? null : response.page + 1;

    //INFO: Algolia page: 0, nbPages: 50, isLastPage: false, nextPageKey: 1
    logger.info('Algolia page: ${response.page}, nbPages: ${response.nbPages}, isLastPage: $isLastPage, nextPageKey: $nextPageKey');

    return _HitsPage(items, response.page, nextPageKey);
  }
}

https://github.com/algolia/algoliasearch-helper-flutter/assets/49754877/12742152-2b9c-44ae-a209-230497cf859f

Patrick386 commented 7 months ago

I accidentally omitted the listener that passes the incremented page key to the page controller. Issue resolved.

reemora commented 6 months ago

لقد كتبت نموذجًا صغيرًا من التعليمات البرمجية للاختبار على النحو التالي. المشكلة هي أنها لا تجلب الصفحة التالية. هل يمكنك المساعدة في تحديد وإصلاح أي مشاكل في الكود؟

class DemoView extends StatefulWidget {
  const DemoView({super.key});

  @override
  State<DemoView> createState() => _DemoViewState();
}

class _DemoViewState extends State<DemoView> {
  final PagingController<int, DemoData> _pagingController =
      PagingController<int, DemoData>(firstPageKey: 0);

  late HitsSearcher _hitsSearcher;
  Stream<_HitsPage> get _searchPage =>
      _hitsSearcher.responses.map(_HitsPage.fromResponse);

  @override
  void initState() {
    _hitsSearcher = HitsSearcher(
      applicationID: Env.algoliaApplicationID,
      apiKey: Env.algoliaApiKey, // adminKey search-only demo key
      indexName: AlgoliaCredentials.demoEcommerceIndex, // demo_ecommerce
    );

    _searchPage.listen((_HitsPage page) {
      if (page.pageKey == 0) {
        _pagingController.refresh();
      }
      logger.info('nextPageKey:${page.nextPageKey} / Page item length:${page.items.length}'); // 1 / 20
      _pagingController.appendPage(page.items, page.nextPageKey);
    }).onError((error) => _pagingController.error = error);

    _pagingController.addStatusListener((status) {
      // status:PagingStatus.ongoing
      logger.info('status:${status.toString()}');
    });
    super.initState();
  }
  @override
  void dispose() {
    _pagingController.dispose();
    _hitsSearcher.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
     appBar: AppBar(),

      body: PagedListView<int, DemoData>(
          pagingController: _pagingController,
          builderDelegate: PagedChildBuilderDelegate<DemoData>(
              noItemsFoundIndicatorBuilder: (_) => const Center(
                    child: Text('No results found')),
              itemBuilder: (_, DemoData item, __) => Container(
                    color: Colors.white,
                    height: 80,
                    padding: const EdgeInsets.all(8),
                    child: Row(
                      children: [
                        if (item.image != null)
                          SizedBox(
                              width: 50, child: Image.network(item.image!)),
                        const SizedBox(width: 20),
                        Expanded(child: Text('${item.name}'))
                      ],
                    ),
                  ))),
    );

  }
}

class _HitsPage {
  const _HitsPage(this.items, this.pageKey, this.nextPageKey);

  final List<DemoData> items;
  final int pageKey;
  final int? nextPageKey;

  factory _HitsPage.fromResponse(SearchResponse response) {
    final items = response.hits.map(DemoData.fromJson).toList();
    final isLastPage = response.page >= response.nbPages;
    final nextPageKey = isLastPage ? null : response.page + 1;

    //INFO: Algolia page: 0, nbPages: 50, isLastPage: false, nextPageKey: 1
    logger.info('Algolia page: ${response.page}, nbPages: ${response.nbPages}, isLastPage: $isLastPage, nextPageKey: $nextPageKey');

    return _HitsPage(items, response.page, nextPageKey);
  }
}

شاشة.تسجيل.2023-11-26.at.4.35.28.PM.mov