Almost every app has a screen that displays a list of items. It is a simple task to do at first sight, and Flutter framework provides ListView widget for that. But it is usually required to implement much related stuff around that. A progress indicator while list items are loading, individual views for empty data and error, pull to refresh and infinite scrolling. All that boilerplate code can be simplified with ListUic widget.

ListUic out of the box

Get started

ListUic is a part of uic (UI Components) package.

To use it in your app add the following dependency in your pubspec.yaml file:

dependencies:

uic: ^0.1.0

And add the following import in the file, that will use ListUic widget:

import 'package:uic/list_uic.dart';

Usage of ListUic is simple as following:

Step 1: Create ListUicController

ListUicController manages ListUic’s state. Further we will look at it in more detail. For now, let’s just create it with basic setup:

class _MyHomePageState extends State<MyHomePage> {

ListUicController<int> _controller;



@override

void initState() {

super.initState();

_controller = ListUicController<int>(

onGetItems: (int page) => _getItems(page),

);

}

}

It is assumed that we will have MyHomePage stateful widget for our list screen. So we will define a _controller variable in the companion _MyHomePageState class.

ListUicController class is a generic and we have to specify a type in the declaration of _controller variable. That is the type of objects which our list will display. In this example the list data are integer numbers, so we used int as a type.

Next, in the initState() method, we create the controller object. Its constructor has the only mandatory onGetItems parameter. This is a callback function, which controller call when it needs to load data for our list. The function has a page parameter and must return a value of Future<List<T>> type.

If you don’t use the pagination, you can ignore the page parameter, and implement the function so it will return the whole data at once. Otherwise the function should return the portion of items by specified page.

We will make a fake implementation of _getItems(page) in step 3. In you real app, I guess the implementation would use your repository to retrieve the data.

Step 2: Adding ListUic widget to the widget tree

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(widget.title),

),

body: ListUic<int>(

controller: _controller,

itemBuilder: (item) {

return ListTile(

title: Text('Title ${item}'),

subtitle: Text('Subtitle ${item}'),

);

},

),

);

}

ListUic class is also a generic, and we have to provide the same int type as for the controller, which we created in step 1.

The ListUic widget constructor requires two parameters:

controller — ListUicController object.

itemBuilder — this is a function that build a list item widget. It is similar to item builder in a ListView widget, which is, I’m sure, familiar to you. But unlike the ListView’s item builder, this function has an item parameter, which is a list item object.

In this example the item builder creates a simple ListTile widget.

ListUic has vary options to customize its appearance. They will be discussed later in this article.

Step 3: Implementing _getItems(page) function

Here is the implementation which returns fake data:

Future<List<int>> _getItems(int page) async {

print("_getItems(): page=$page");

await Future.delayed(Duration(seconds: 3));

List<int> result = List();

for (int i = 1; i <= 10; i++) {

result.add((page - 1) * 10 + i);

}

return result;

}

It returns the list of numbers according to specified page. For page 1 it will return 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, for page 2 — 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, and so on.

In the real app, of course, you will load items from the network, or from the local storage, and probably will use a repository.

That is all you need to start using ListUic. With this basic setup it will show the progress view while data is loading, perform data loading, show error messages. A user will be able to use pull to refresh gesture to reload the data, or scroll to the end of list to load next page of data.

You can find the full code of example app in the UIC package repository: https://github.com/ech89899/uic-flutter/blob/master/example/lib/main.dart