Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infinite List in Flutter Application

I am migrating my application from android to flutter and till now I have used ListView in a flutter. my question is, is there any specialized technique to handle a large amount of data in the flutter? for reference, you can look at android RecyclerView. it handles in-memory views and recycles its runtime. so how to achieve functionality like RecyclerView in Flutter? or it's not necessary for the flutter?

like image 571
Kiran Maniya Avatar asked Nov 02 '18 08:11

Kiran Maniya


People also ask

How do you get infinite scroll on flutter?

Implementing infinite scroll using ScrollController You can use the ScrollController to listen to scrollable widgets like the ListView , GridView and CustomScrollView . In the context of our tutorial application, the ScrollController will be responsible for monitoring how far the user has scrolled down the page.

How do you limit lists on flutter?

Flutter ListView – Set or Limit Height To limit the height of ListView, wrap the ListView with a Container widget and set the height of the Container to the required height.

How do you create a dynamic list in flutter?

Create Dynamic ListView using ListView. builder() And you would not know the number of elements in the list beforehand. In such scenarios, you can use ListView. builder() constructor of ListView class to create a dynamic list of widgets in ListView widget.


2 Answers

The easiest way is to use a ListView.builder without specifying the itemCount parameter.

Here is the simplest example:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Infinite List"),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          return Text("$index");
        },
      ),
    );
  }
}

Later, you can enhance this by fetching real data. You could show a 'CircularProgressIndicator' in the last item of the list while waiting for the new data.

  body: ListView.builder(
    itemBuilder: (context, index) {
      if (index < data.length) {
        // Show your info
        return Text("$index");
      } else {
        getMoreData();
        return Center(child: CircularProgressIndicator());
      }
    },
    itemCount: data.length + 1,
  ),

You can see that we trick the list by adding an index, and calling for more data when displaying that final index.

getMoreData() would include a call to setState() to force a rebuild and to take into account the new data.

like image 103
chemamolins Avatar answered Oct 05 '22 05:10

chemamolins


Below is a simple infinite list widget based on chemamolins's answer. It accepts an itemBuilder to build the current item and onRequest callback to request more data when the user scrolls to the bottom.

import 'package:flutter/material.dart';

typedef Future<List<T>> RequestFn<T>(int nextIndex);
typedef Widget ItemBuilder<T>(BuildContext context, T item, int index);

class InifiniteList<T> extends StatefulWidget {
  final RequestFn<T> onRequest;
  final ItemBuilder<T> itemBuilder;

  const InifiniteList(
      {Key? key, required this.onRequest, required this.itemBuilder})
      : super(key: key);

  @override
  _InifiniteListState<T> createState() => _InifiniteListState<T>();
}

class _InifiniteListState<T> extends State<InifiniteList<T>> {
  List<T> items = [];
  bool end = false;

  _getMoreItems() async {
    final moreItems = await widget.onRequest(items.length);
    if (!mounted) return;

    if (moreItems.isEmpty) {
      setState(() => end = true);
      return;
    }
    setState(() => items = [...items, ...moreItems]);
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (context, index) {
        if (index < items.length) {
          return widget.itemBuilder(context, items[index], index);
        } else if (index == items.length && end) {
          return const Center(child: Text('End of list'));
        } else {
          _getMoreItems();
          return const SizedBox(
            height: 80,
            child: Center(child: CircularProgressIndicator()),
          );
        }
      },
      itemCount: items.length + 1,
    );
  }
}

Usage

child: InifiniteList<String>(
  onRequest: requestItems,
  itemBuilder: (context, item, index) => Container(
    padding: const EdgeInsets.all(30),
    color: index % 2 == 0 ? Colors.purple.shade100 : Colors.lime.shade100,
    child: Text(item, style: Theme.of(context).textTheme.headline6),
  ),
),
// normally this is the place where you request the next batch of items
// on the network.
Future<List<String>> requestItems(int nextIndex) {
  const pageSize = 15;
  var result = List<String>.generate(pageSize, (i) => "Item: ${nextIndex + i + 1}");
  return Future<List<String>>.delayed(
    const Duration(milliseconds: 500),
    () => result,
  );
}

Live Demo

like image 40
NearHuscarl Avatar answered Oct 05 '22 05:10

NearHuscarl