Трепетание при обновлении ListView.builder возвращается с начала, а не с точки maxScrollExtent

#flutter

#flutter

Вопрос:

Я новичок в Flutter, и я столкнулся с проблемой.

Что у меня есть до сих пор, так это то, что я получаю данные из веб-службы асинхронно (Json). Итак, в методе сборки я использую FutureBuilder виджет для аргумента тела Scaffold. И его аргумент ‘builder’ ( FutureBuilder виджета) возвращает a ListView.builder для отображения данных. Также я использую ScrollController для прокрутки.

Когда я достигаю максимальной точки прокрутки, я снова вызываю службу, чтобы получить следующую страницу данных и так далее…

Проблема в том, что когда я «меняю страницу» с помощью прокрутки, данные отображаются правильно, но они начинаются с самой первой строки данных, а не с точки, в которой я достиг maxScrollExtent точки.

Итак, если первый «снимок» содержит 25 строк, а второй — 15, когда я перехожу ко второму, он начинается со строки 1, а не со строки 26, хотя общее количество строк данных правильно равно 40.

В результате у меня нет плавной прокрутки. Я застрял на достаточно долгое время до этого момента, и я не знаю, чего мне не хватает. Должен ли я использовать ключи хранения страниц (я видел видео от команды flutter, но я не нашел решения своей проблемы). Какие-либо подсказки? Далее следует пример кода.

 class _MyAppState extends State<MyApp> {
  
  final ScrollController _controller = ScrollController();
  @override
  void initState() {
    super.initState();
    _controller.addListener(_scrollListener);
  }
  void _scrollListener() {
    if (_controller.offset >= _controller.position.maxScrollExtent amp;amp;
        !_controller.position.outOfRange) {

      if (nextDataSet != null) {
        print('nextDataSet = '   nextDataSet);
        setState(() {
          inDataSet = nextDataSet;
        });
      } else {
        print('nextDataSet = NULL');
      }

  }

  Future<Post> fetchPost([String dataSet]) async {
  ...
  return Post.fromJson(json.decode(utf8.decode(response.bodyBytes)));
  }

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Scaffold(
        ...
        body: FutureBuilder<Post>(
                  future: fetchPost(inDataSet),
                  builder: _buildList,
                ),
        ),
      ),
    );
    }

  Widget _buildList(BuildContext context, AsyncSnapshot snapshot) {
     ... /*code that eventually fills the lists of strings 
         progressivePartyListSec, progressivePartyListThird*/
     ...
     return ListData(controller: _controller, listEidosPerigr: 
     progressivePartyListSec, listPerigr: progressivePartyListThird );
  }

}

class ListData extends StatelessWidget {

  final ScrollController controller;
  final List<String> listEidosPerigr;
  final List<String> listPerigr;

  ListData({this.controller,
    this.listEidosPerigr,
    this.listPerigr});

  @override
  Widget build(BuildContext context) {

    return ListView.builder(
        controller: controller,
        itemCount: rowsSelected,
        itemBuilder: (context, i) {
          return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  removeAllHtmlTags(listEidosPerigr[i]),
                  style: TextStyle(
                      fontWeight: FontWeight.bold, color: Colors.blue),
                ),
                new RichText(
                  text: new TextSpan(
                      text: listPerigr[i].replaceAllMapped('<BR>', (Match m) => '').replaceAllMapped('<b>', (Match m) => '').replaceAllMapped('</b>', (Match m) => ''),
                      style: DefaultTextStyle.of(context).style,
                  ),
                ),
              ]);
        });
  }
}
  

Комментарии:

1. Не могли бы вы добавить больше кода

2. Да, конечно, я добавил соответствующий код…

Ответ №1:

после некоторых исследований я нашел решение по следующей ссылке: Flutter: создание ListView, которое загружает по одной странице за раз

Большое спасибо Абдулрахману Альхамали.

В принципе, в приведенном выше коде, который я опубликовал, я использовал другой аргумент для ListView.builder, и это следующий ключ: PageStorageKey(‘offset’),

Наконец, как пишет Абдулрахман в своей статье, я использовал KeepAliveFutureBuilder в качестве оболочки FutureBuilder в других мирах в моем методе сборки, который я сделал…

 body: KeepAliveFutureBuilder(
            //child: FutureBuilder<Post>(
                future: fetchPost(inDataSet),
                builder: _buildList,
              //),
          ),