Home > Net >  How to fetch data from REST API and display on Listview, Flutter
How to fetch data from REST API and display on Listview, Flutter

Time:09-28

I am fairly new to using REST API to GET data and display in a Listview in Flutter. I have since been working on something like this, But i get Lost along the line. Hence I need Help with this.

My code Goes thus

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';

import 'package:http/http.dart' as http;

class TransactionDetails {
  final String avatar;
  final String name;
  final String date;
  final String amount;

  TransactionDetails({required this.avatar, required this.name, required this.date, required this.amount});

  factory TransactionDetails.fromJson(Map<String, dynamic> json) {
    return TransactionDetails(
        avatar: json['avatar'],
        name: json['name'],
        date: json['date'],
        amount: json['amount']);
  }
}

class BaseScreen extends StatelessWidget {
  const BaseScreen({Key? key}) : super(key: key);

  Future<TransactionDetails> fetchTransaction() async {
    final response = await http
        .get('https://brotherlike-navies.000webhostapp.com/people/people.php');

    if (response.statusCode == 200) {
      return TransactionDetails.fromJson(json.decode(response.body));
    } else {
      throw Exception('Request Failed.');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
            child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          width: double.infinity,
          height: 150,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: [
              Container(
                margin: const EdgeInsets.all(15),
                width: 319,
                height: 100,
                color: Colors.green,
                alignment: Alignment.center,
                child: const Text(
                  '\$5200.00',
                  style: TextStyle(
                      fontSize: 15,
                      color: Colors.white,
                      fontWeight: FontWeight.bold),
                ),
              ),
              Container(
                margin: const EdgeInsets.all(15),
                width: 319,
                height: 100,
                color: Colors.green,
                alignment: Alignment.center,
                child: const Text(
                  '\$1200.00',
                  style: TextStyle(
                      fontSize: 15,
                      color: Colors.white,
                      fontWeight: FontWeight.bold),
                ),
              ),
              SizedBox(height: 24),
            ],
          ),
        ),
        Padding(
          padding: EdgeInsets.all(15),
          child: Text(
            "Recent Transactions",
            style: TextStyle(
                fontSize: 14, fontWeight: FontWeight.bold, color: Colors.green),
          ),
        ),
        ListView() //Display the data here from the REST API
      ],
    )));
  }
}

How do I Display it on the Listview? Please I need help with this. Just for the sake of clarification as I am learning here with this.

CodePudding user response:

Try below code:

Your TransactionDetails Class

class TransactionDetails {
  String? avatar;
  String? name;
  String? date;
  String? amount;

  TransactionDetails({
    this.avatar,
    this.name,
    this.date,
    this.amount,
  });

  TransactionDetails.fromJson(Map<String, dynamic> json) {
    avatar = json['avatar'];
    name = json['name'];
    date = json['date'];
    amount = json['amount'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['avatar'] = avatar;
    data['name'] = name;
    data['date'] = date;
    data['amount'] = amount;
    return data;
  }
}

API Call:

 Future<List<TransactionDetails>> fetchAlbum() async {
    final response = await http.get(Uri.parse(
        'https://brotherlike-navies.000webhostapp.com/people/people.php'));

    if (response.statusCode == 200) {
      final List result = json.decode(response.body);
      return result.map((e) => TransactionDetails.fromJson(e)).toList();
    } else {
      throw Exception('Failed to load data');
    }
  }

Your Widget:

Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          width: double.infinity,
          height: 150,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: [
              Container(
                margin: const EdgeInsets.all(15),
                width: 319,
                height: 100,
                color: Colors.green,
                alignment: Alignment.center,
                child: const Text(
                  '\$5200.00',
                  style: TextStyle(
                      fontSize: 15,
                      color: Colors.white,
                      fontWeight: FontWeight.bold),
                ),
              ),
              Container(
                margin: const EdgeInsets.all(15),
                width: 319,
                height: 100,
                color: Colors.green,
                alignment: Alignment.center,
                child: const Text(
                  '\$1200.00',
                  style: TextStyle(
                      fontSize: 15,
                      color: Colors.white,
                      fontWeight: FontWeight.bold),
                ),
              ),
              const SizedBox(height: 24),
            ],
          ),
        ),
        const Padding(
          padding: EdgeInsets.all(15),
          child: Text(
            "Recent Transactions",
            style: TextStyle(
                fontSize: 14,
                fontWeight: FontWeight.bold,
                color: Colors.green),
          ),
        ),
        Center(
          child: FutureBuilder<List<TransactionDetails>>(
            future: fetchAlbum(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return ListView.builder(
                  shrinkWrap: true,
                  itemCount: snapshot.data!.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      leading: CircleAvatar(
                        child: Image.network(
                            snapshot.data![index].avatar.toString()),
                      ),
                      title: Text(snapshot.data![index].name.toString()),
                      trailing:
                          Text(snapshot.data![index].amount.toString()),
                      subtitle: Text(snapshot.data![index].date.toString()),
                    );
                  },
                );
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              } 
              return const CircularProgressIndicator();
            },
          ),
        ),
      ],
    ),

Result Screen-> image

CodePudding user response:

There are multiple ways you can achieve this.

  1. Using FutureBuilder
  2. Using StatefulWidget & setState

Currently, you are using a StatelessWidget (BaseScreen) so let's just go with FutureBuilder.

On hitting the url that you have given: https://brotherlike-navies.000webhostapp.com/people/people.php

It gives the following response:

[{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/002\/002\/403\/small\/man-with-beard-avatar-character-isolated-icon-free-vector.jpg","name":"Kayo Johnson","date":"09\/29\/2022","amount":"5000.00"},{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/002\/002\/403\/small\/man-with-beard-avatar-character-isolated-icon-free-vector.jpg","name":"Kuta Joy","date":"09\/29\/2022","amount":"5000.00"},{"avatar":"https:\/\/static.vecteezy.com\/system\/resources\/thumbnails\/001\/993\/889\/small\/beautiful-latin-woman-avatar-character-icon-free-vector.jpg","name":"Timmi Phillips","date":"09\/28\/2022","amount":"3500.00"}]

It returns a list of transaction details objects. Hence, you should add another method in your model TransactionDetail which will return a list of TransactionDetails as follows:

class TransactionDetails {
  final String avatar;
  final String name;
  final String date;
  final String amount;

  TransactionDetails(
      {required this.avatar,
      required this.name,
      required this.date,
      required this.amount});

  factory TransactionDetails.fromJson(Map<String, dynamic> json) {
    return TransactionDetails(
        avatar: json['avatar'],
        name: json['name'],
        date: json['date'],
        amount: json['amount']);
  }

  static List<TransactionDetails> fromJsonList(dynamic jsonList) {
    final transactionDetailsList = <TransactionDetails>[];
    if (jsonList == null) return transactionDetailsList;

    if (jsonList is List<dynamic>) {
      for (final json in jsonList) {
        transactionDetailsList.add(
          TransactionDetails.fromJson(json),
        );
      }
    }

    return transactionDetailsList;
  }
}

Update your fetchTransaction method as follows:

Future<List<TransactionDetails>> fetchTransaction() async {
    final response = await http
        .get('https://brotherlike-navies.000webhostapp.com/people/people.php');

    if (response.statusCode == 200) {
      return TransactionDetails.fromJsonList(json.decode(response.body));
    } else {
      throw Exception('Request Failed.');
    }
  }

Just wrap your ListView widget with a FutureBuilder widget as follows:

    FutureBuilder(
      future: fetchTransaction(),
      builder: (context, AsyncSnapshot<List<TransactionDetails>> snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          if (snapshot.data == null) {
            return const Center(child: Text('Something went wrong'));
          }

          return ListView.builder(
              itemCount: snapshot.data?.length ?? 0,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(snapshot.data![index].name),
                  subtitle: Text(snapshot.data![index].amount),
                );
              });
        }
        return const CircularProgressIndicator();
      },
    ),
  • Related