Flutter: Usando o Riverpod Future Provider para buscar API

Tempo de leitura: 3 minutes

As operações assíncronas estão em quase todos os aplicativos que funcionam com back-end. Quer seja GraphQL, Rest ou qualquer outra coisa, você tem o mesmo padrão. Você inicia a solicitação e espera até que ela seja concluída antes de mostrar os dados. No Flutter, Riverpod nos fornece o FutureProvider. Com o FutureProvider, a UI pode lidar com isso de forma síncrona. O FutureProvider informará aos Widgets quando os dados estiverem prontos ou quando a chamada falhou.

 

FutureProvider

Este provedor é de alguma forma uma combinação de Provider<T> e FutureBuilder, nesse sentido você pode criar um valor síncrono e observar alterações nele, como se ele fosse recuperado com sucesso.

Riverpod remove as redundâncias de usar algo como FutureBuilder e manipula automaticamente o código.

Como visto, _data é um tipo de AsyncValue<T> que fornece ao método when opções para data(), loading() e error() que podemos manipular conforme necessário.

Isso é muito mais fácil do que usar FutureBuilder ou StreamProvider. Incrível, certo?

Vamos começar. Explicarei o tratamento da API com uma solicitação get.

Vamos instalar os pacotes http e flutter_riverpod. Certifique-se de instalar a versão mais recente.

dependencies:
  http: ^0.13.6
  flutter_riverpod: ^2.4.6

Instale o pacote. Execute o comando para obter o pacote.

Instale o pacote. Você pode salvar o arquivo pubspec.yaml.

flutter pub get

Estrutura de pastas:

API:https://reqres.in/api/users?page=2

Estrutura de pastas: primeiro vamos começar criando a classe Model

user_model.dart

class UserModel {
  final int id;
  final String email;
  final String firstname;
  final String lastname;
  final String avatar;
  UserModel(
      {required this.id,
      required this.email,
      required this.firstname,
      required this.lastname,
      required this.avatar});

  factory UserModel.fromJson(Map<String, dynamic> json) {
    return UserModel(
        id: json['id'],
        email: json['email'],
        firstname: json['first_name'] ?? 'First Name',
        lastname: json['last_name'] ?? 'Last Name',
        avatar: json['avatar'] ??
            'https://img.freepik.com/free-vector/illustration-user-avatar-icon_53876-5907.jpg?w=740');
  }
}

Em segundo lugar, criaremos uma classe de serviço API e definiremos o método para decodificar API com pacote Http

class ApiService {
  String endpoint = 'https://reqres.in/api/users?page=2';

  Future<List<UserModel>> getUser() async {
    Response response = await get(Uri.parse(endpoint));
    if (response.statusCode == 200) {
      final List result = jsonDecode(response.body)['data'];
      return result.map(((e) => UserModel.fromJson(e))).toList();
    } else {
      throw Exception(response.reasonPhrase);
    }
  }
}

//Provedor de SERVIÇO API
final apiProvider = Provider<ApiService>((ref) => ApiService());

Aqui usamos a referência Provider apiProvider normal APIService() inteira

Em terceiro lugar, acessamos a API via FutureProvider

Para acessar os dados da API, criamos um provedor do userDataProvider. Podemos acessar esta APIclass no FutureProvider. O FutureProvider retornará a lista de <UserModel>

que fornecemos pelo apiProvider.

final userDataProvider = FutureProvider<List<UserModel>>((ref) async {
  return ref.read(apiProvider).getUser();
});

 

Finalmente, vamos iniciar a IU

Primeiro, podemos criar um novo ConsumerWidget para usar a função ref.watch para recuperar os artigos. Então, podemos usar a função when no Future que recuperamos com o gancho. Com base no estado atual, podemos retornar o widget correto. Quando os artigos estiverem carregando, retornaremos o CircularProgressIndicator. Se os artigos estiverem prontos, podemos exibi-los com um simples ListView e ListTile.

class Homepage extends ConsumerWidget {
  const Homepage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, ref) {
    final _data = ref.watch(userDataProvider);
    return Scaffold(
        appBar: AppBar(
          title: const Text('User Profile'),
        ),
        body: _data.when(
          data: (_data) {
            return Column(
              children: [
                ..._data.map((e) => ListView(shrinkWrap: true, children: [
                      InkWell(
                        onTap: () => Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (context) => DetailPage(
                              e: e,
                            ),
                          ),
                        ),
                        child: ListTile(
                          title: Text(e.firstname),
                          subtitle: Text(e.lastname),
                          trailing: CircleAvatar(
                            backgroundImage: NetworkImage(e.avatar),
                          ),
                        ),
                      ),
                    ])),
              ],
            );
          },
          error: (err, s) => Text(err.toString()),
          loading: () => const Center(
            child: CircularProgressIndicator(),
          ),
         
        ),);
  }
}

 

Código Completo no Meu GitHub: (link)