Monday, September 27, 2021

Flutter - Fetch data from the internet | Network Request | Fetch and display the data with Flutter | Networking in Flutter using the http package | How to point to localhost:8000 with the Dart http package in Flutter

Today we will try to fetch the data from an API into a Flutter app.
Firstly, we need to import the http package, which provides the simplest way to fetch data from the internet into our project.

Update your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  http: # add this yours
Future is a core Dart class for working with async operations. A Future object represents a potential value or error that will be available at some time in the future.

The http.Response class contains the data received from a successful http call.

Although it’s convenient, it’s not recommended to put an API call in a build() method.

Flutter calls the build() method every time it needs to change anything in the view, and this happens surprisingly often. Leaving the fetch call in your build() method floods the API with unnecessary calls and slows down your app.

The http.get() method is used to make a request to the specified ‘url’ and http.Response class contains the data received from a successful http call. We make this function of type Future because we will get the response for the request at some time in the future, not immediately.

Future<http.Response> fetchPost() {
  return http.get('https://base.url/api/account/get/x0303');
}
Usually, the returning response will have information about the status of the request call, which can be accessed using response.statusCode.

import 'package:http/http.dart' as http;
Future<Object> fetchPost() async {
  final response = await http.get(Uri.parse('https://base.url/api/account/get/x0303'));

  if (response.statusCode == 200) {
    print(" Status: OK")
	return json.decode(response.body);
  }
  else {
    throw Exception('Failed to get data');
  }
}
Full example is as below

import 'dart:convert';

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ApplicationBase(),
    );
  }
}

class ApplicationBase extends StatefulWidget {
  const ApplicationBase({Key? key}) : super(key: key);

  @override
  _ApplicationBaseState createState() => _ApplicationBaseState();
}

class _ApplicationBaseState extends State<ApplicationBase> {
  @override
  void initState() {
    super.initState();
  }

  Future<String> _calculation = Future<String>.delayed(
    Duration(seconds: 2), () => loadDataAsync(),
  );

  // flutter thread to load data
  static Future<String> loadDataAsync() async {
    return Future.delayed(Duration(seconds: 0), () async {
      final response = await http.get(Uri.parse('https://base.url/api/account/get/x0303'));

      if (response.statusCode == 200) {
        var data = json.decode(response.body);
        return data["result"] == null ? throw Exception(data["error"].toString()) : data["result"];
      }
      else {
        throw Exception('Failed to get data');
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    //_onPressed(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("My Test App"),
      ),
      body: Center(
          child: FutureBuilder<String>(
            future: _calculation,
            builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
              List<Widget> children;

              if (snapshot.hasData) {
                children = <Widget>[
                  Text("Data loaded from http call = ${snapshot.data}")
                ];
              }
              else if (snapshot.hasError) {
                children = <Widget>[
                  Icon(
                    Icons.error_outline,
                    color: Colors.red,
                    size: 60,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: Text('Error: ${snapshot.error}'),
                  )
                ];
              }
              else {
                children = <Widget>[
                  SizedBox(height: 20),
                  SizedBox(
                    child: CircularProgressIndicator(),
                    width: 60,
                    height: 60,
                  ),
                  const Padding(
                    padding: EdgeInsets.only(top: 16),
                    child: Text('Awaiting result...'),
                  )
                ];
              }
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: children,
                ),
              );
            }
          )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const ApplicationBase()),
          );
        },
        child: Icon(Icons.add),
      ),
    );
  }
}
For test purpose, if you want to call your localhost from Flutter then do the below:

replace 'localhost' in your url to wifi connection ip e.g : 'http://localhost:8000' => 'http://192.168.1.102:8000'. you can get your wifi ip from command prompt with cmd>ipconfig (wireless LAN adapter WI-FI.

Sample screen shot


1 comment:

  1. very clear and detailed example - thanks...

    ReplyDelete