This is a continuation for the first post Flutter BLoC & GraphQL

I will modify the code in ./lib/screens/home/home_screen.dart to add pull-to-refresh functionality.

Make it Stateful

Make the HomeScreen class extends StatefulWidget

Converting a StatelessWidget to StatefulWidget is just a click away thanks to the Flutter extension for IntelliJ & VSCode.

Track the list of posts

Create a variable in the _HomeScreenState class to hold the list of posts, List<GetPosts$Query$Post> _posts = [];.

Add BlocListener

The BlocListener is different from BlocBuilder ;that we used in the previous post; in the BlocListener we have listener function which will be called once and only once per state change.

In the listener function we will check if the state is HomeLoadedState then set the _posts variable to state.posts.

Pull to refresh

Or sometimes called swipe to refresh is as simple as wrapping ListView.builder with RefreshIndicator and in onRefresh function we will reset _posts and add a new action to reload BlocProvider.of<HomeBloc>(context).add(HomeLoadEvent());.

Final code

Link to full code up to here https://github.com/agent3bood/Flutter-architecture-app/tree/pull-to-refresh

./screens/home/home_screen.dart

import 'package:architecture_app/graphql/graphql_api.graphql.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'bloc.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<GetPosts$Query$Post> _posts = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Architecture demo'),
      ),
      body: Container(
        child: BlocListener<HomeBloc, HomeState>(
          listener: (context, state) {
            if (state is HomeLoadedState) {
              _posts.addAll(state.posts);
            }
          },
          child: BlocBuilder<HomeBloc, HomeState>(
            builder: (context, state) {
              if (state is HomeLoadingState) {
                return Container(
                  child: Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              } else if (state is HomeLoadedState) {
                return RefreshIndicator(
                  onRefresh: () async {
                    _posts = [];
                    BlocProvider.of<HomeBloc>(context).add(
                      HomeLoadEvent(),
                    );
                  },
                  child: ListView.builder(
                    itemCount: _posts.length,
                    itemBuilder: (context, index) {
                      final post = _posts[index];
                      return ListTile(
                        key: Key(post.id),
                        title: Text(post.title),
                        subtitle: Text('By: ${post.author.name}'),
                      );
                    },
                  ),
                );
              } else {
                return Container(
                  child: Center(
                    child: Text('You have an error'),
                  ),
                );
              }
            },
          ),
        ),
      ),
    );
  }
}