Streams with ListView and Smooth Scrolling

Muhammad Mashood Siddiquie
Analytics Vidhya
Published in
3 min readJun 26, 2020

Hello Everyone today we’ll be discussing how to use streams with listview to build items when users reached that particular position of the item, We will be using JSON Place Holder API of Photos containing 5000 images, we will learn at the end of the article that how to have smooth scrolling using stream controller and listview, so without wasting time let’s start ❤

Create a new flutter project with the name “flutter_stream_project” and make sure you have this project structure:

Now first create a model class with name “Photo” and copy-paste the following code:

class Photo {
final String title;
final String url;

Photo.fromJsonMap(Map map)
: title = map['title'],
url = map['url'];
}

As we want only the image URL and title from the JSON place holder API.

fromJsonMap is to map the JSON data into a map.

Now let’s create a new file inside screens folder with name PhotoList, and copy-paste the following code:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutterstreamproject/models/Photo.dart';
import 'dart:convert';

import 'package:http/http.dart' as http;
class PhotoList extends StatefulWidget {
@override
_PhotoListState createState() => _PhotoListState();
}

class _PhotoListState extends State<PhotoList> {
StreamController<Photo> _streamController;
List<Photo> list = [];

@override
void initState() {
super.initState();
_streamController = StreamController.broadcast();

_streamController.stream.listen((p) => setState(() => list.add(p)));

load(_streamController);
}

load(StreamController<Photo> sc) async {
String url = "https://jsonplaceholder.typicode.com/photos";
var client = new http.Client();

var req = new http.Request('get', Uri.parse(url));

var streamedRes = await client.send(req);

streamedRes.stream
.transform(utf8.decoder)
.transform(json.decoder)
.expand((e) => e)
.map((map) => Photo.fromJsonMap(map))
.pipe(sc);
}

@override
void dispose() {
super.dispose();
_streamController?.close();
_streamController = null;
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Photo Streams"),
),
body: Center(
child: ListView.builder(
// scrollDirection: Axis.horizontal,

itemBuilder: (BuildContext context, int index) => _makeElement(index),
itemCount: list.length,
),
),
);
}

Widget _makeElement(int index) {
if (index >= list.length) {
return null;
}

return Container(
padding: EdgeInsets.all(5.0),
child: Padding(
padding: EdgeInsets.only(top: 200.0),
child: Column(
children: <Widget>[
Image.network(list[index].url, width: 150.0, height: 150.0),
Text(list[index].title),
],
),
));
}
}

Here we create a stream controller as a stream controller is a generic type so we need to define the datatype inside <> angular brackets, as we want the photo data so we pass the photo model inside angular brackets, now to initialize the stream controller we need the init state now we broadcast the stream controller i.e we subscribe to the stream controller for every change and after that we use listen method and pass p which can anything but related to the photo model class we passed in stream controller now we want changes whenever a new item is added in a list so we add the p in our list which is a photo model and then we create a method load with args as stream controller, now a load method we call our API with a get request and map the result of the stream with the help of Photo model class fromJsonMap method and then we call the dispose method to dispose all the stream controller and pass null also so that if we navigate to another screen etc so it wont take any memory or doesn't cause any memory leakage.

Now we create a simple UI with listview.builder, in which item builder we create a method makeElement which have a container and having a child as column and pass the Network image and text widget.

Now let’s run the app the UI won't be great but you’ll notice how the scrolling becomes so much smoother with this approach and also we subscribe to the changes whenever a new item added the stream controller change method will be call and make a change sudden.

I hope you understand it that how to use stream controller with listview and API, Wish to see you guys commenting out and giving a clap on this article.

Thank you ❤.

Github Repo link of sample project :

https://github.com/Mashood97/flutter_stream_project

--

--