Flutter – Accessing REST API

Flutter - Accessing REST API

 

Flutter provides http package to consume HTTP resources. http is a Future-based library and uses await and async features. It provides many high level methods and simplifies the development of REST based mobile applications.

Basic Concepts

http package provides a high level class and http to do web requests.

  • http class provides functionality to perform all types of HTTP requests.
  • http methods accept a url, and additional information through Dart Map (post data, additional headers, etc.,). It requests the server and collects the response back in async/await pattern. For example, the below code reads the data from the specified url and print it in the console.
print(await http.read('https://flutter.dev/'));

 

Some of the core methods are as follows −

  • read − Request the specified url through GET method and return back the response as Future<String>
  • get − Request the specified url through GET method and return back the response as Future<Response>. Response is a class holding the response information.
  • post − Request the specified url through POST method by posting the supplied data and return again the response as Future<Response>
  • put − Request the specified url through PUT method and return back the response as Future <Response>
  • head − Request the specified url through HEAD method and return back the response as Future<Response>
  • delete − Request the specified url through DELETE method and return back the response as Future<Response>

http additionally supplies a extra customary HTTP shopper class, shopper. shopper helps persistent connection. It shall be helpful when lots of request to be made to a specific server. It must be closed correctly utilizing shut technique. Otherwise, it's much like http class. The pattern code is as follows −

var shopper = new http.Client(); 
attempt  
lastly

 

Accessing Product service API

Let us create a easy software to get product knowledge from an internet server after which present the merchandise utilizing ListView.

  • Create a brand new Flutter software in Android studio, product_rest_app.
  • Replace the default startup code (essential.dart) with our product_nav_app code.
  • Copy the belongings folder from product_nav_app to product_rest_app and add belongings contained in the pubspec.yaml file.
flutter: 
   belongings: 
      - belongings/appimages/floppy.png 
      - belongings/appimages/iphone.png 
      - belongings/appimages/laptop computer.png 
      - belongings/appimages/pendrive.png 
      - belongings/appimages/pixel.png 
      - belongings/appimages/pill.png

 

  • Configure http bundle within the pubspec.yaml file as proven beneath
dependencies:
http: ^0.12.0+2

 

  • Here, we'll use the newest model of the http bundle. Android studio will ship a bundle alert that the pubspec.yaml is up to date.

Latest Version

  • Click Get dependencies possibility. Android studio will get the bundle from Internet and correctly configure it for the applying.
  • Import http bundle in the primary.dart file −
import 'dart:async';
import 'dart:convert';
import 'bundle:http/http.dart' as http;

 

  • Create a brand new JSON file, merchandise.json with product data as proven beneath
[ 
   { 
      "name": "iPhone", 
      "description": "iPhone is the stylist phone ever", 
      "price": 1000, 
      "image": "iphone.png" 
   }, 
   { 
      "name": "Pixel", 
      "description": "Pixel is the most feature phone ever", 
      "price": 800, 
      "image": "pixel.png"
   }, 
   { 
      "name": "Laptop", 
      "description": "Laptop is most productive development tool", 
      "price": 2000, 
      "image": "laptop.png" 
   }, 
   { 
      "name": "Tablet", 
      "description": "Tablet is the most useful device ever for meeting", 
      "price": 1500, 
      "image": "tablet.png" 
   }, 
   { 
      "name": "Pendrive", 
      "description": "Pendrive is useful storage medium", 
      "price": 100, 
      "image": "pendrive.png" 
   }, 
   { 
      "name": "Floppy Drive", 
      "description": "Floppy drive is useful rescue storage medium", 
      "price": 20, 
      "image": "floppy.png" 
   } 
]

 

  • Create a brand new folder, JSONWebServer and place the JSON file, merchandise.json.
  • Run any net server with JSONWebServer as its root listing and get its net path. For instance, http://192.168.184.1:8000/products.json. We can use any net server like apache, nginx and so on.,
  • The easiest method is to put in node based mostly http-server software. Follow the steps given beneath to put in and run http- server software
    • Install Nodejs software (nodejs.org)
    • Go to JSONWebServer folder.
cd /path/to/JSONWebServer

 

  • Install http-server bundle utilizing npm.
npm set up -g http-server

 

  • Now, run the server.
http-server . -p 8000

Starting up http-server, serving .
Available on:
http://192.168.99.1:8000
http://127.0.0.1:8000
Hit CTRL-C to cease the server

 

  • Create a brand new file, Product.dart within the lib folder and transfer the Product class into it.
  • Write a manufacturing facility constructor within the Product class, Product.fromMap to transform mapped knowledge Map into the Product object. Normally, JSON file shall be transformed into Dart Map object after which, transformed into related object (Product).
manufacturing facility Product.fromJson(Map<String, dynamic> knowledge) 
   return Product(
      knowledge['name'],
      knowledge['description'], 
      knowledge['price'],
      knowledge['image'],
   );

 

  • The full code of the Product.dart is as follows −
class Product {
   ultimate String title; 
   ultimate String description;
   ultimate int value;
   ultimate String picture; 
   
   Product(this.title, this.description, this.value, this.picture); 
   manufacturing facility Product.fromMap(Map<String, dynamic> json) { 
      return Product( 
         json['name'], 
         json['description'], 
         json['price'], 
         json['image'], 
      );
   }
}

 

  • Write two strategies − parseProducts and fetchProducts - in the primary class to fetch and cargo the product data from net server into the List<Product> object.
List<Product> parseProducts(String responseBody)  
   ultimate parsed = json.decode(responseBody).solid<Map<String, dynamic>>(); 
   return parsed.map<Product>((json) =>Product.fromJson(json)).toList(); 
 
Future<List<Product>> fetchProducts() async { 
   ultimate response = await http.get('http://192.168.1.2:8000/products.json'); 
   if (response.statusCode == 200)  
      return parseProducts(response.physique); 
    else  
      throw Exception('Unable to fetch merchandise from the REST API');
    
}

 

  • Note the next factors right here
    • Future is used to lazy load the product data. Lazy loading is an idea to defer the execution of the code till it's vital.
    • http.get is used to fetch the info from the Internet.
    • json.decode is used to decode the JSON knowledge into the Dart Map object. Once JSON knowledge is decoded, it will likely be transformed into List<Product> utilizing fromMap of the Product class.
    • In MyApp class, add new member variable, merchandise of kind Future<Product> and embody it in constructor.
class MyApp extends Statemuch lessWidget {
ultimate Future<List<Product>> merchandise;
MyApp(Key key, this.merchandise) : tremendous(key: key);
...

 

  • In MyHomePage class, add new member variable merchandise of kind Future<Product> and embody it in constructor. Also, take away objects variable and its related technique, getProducts technique name. Placing the merchandise variable in constructor. It will permit to fetch the merchandise from Internet solely as soon as when the applying is first began.
class MyHomePage extends Statemuch lessWidget {
ultimate String title;
ultimate Future<ListList<Product>> merchandise;
MyHomePage() : tremendous(key: key);
...

 

  • Change the house possibility (MyHomePage) within the construct technique of MyApp widget to accommodate above modifications
house: MyHomePage(title: 'Product Navigation demo house web page', merchandise: merchandise),

 

  • Change the primary perform to incorporate Future<Product> arguments −
void essential() => runApp(MyApp(fetchProduct()));

 

  • Create a brand new widget, ProductFieldList to construct the product listing within the house web page.
class ProductFieldList extends Statemuch lessWidget { 
   ultimate List<Product> objects;
   ProductFieldList(); 
   
   @override 
   Widget construct(BuildContext context) {
      return ListView.builder(
         itemCount: objects.size,
         itemBuilder: (context, index) {
            return GestureDetector(
               baby: ProductField(merchandise: objects[index]), 
               onTap: () , 
            ); 
         }, 
      ); 
   } 
}

 

Note that we used the identical idea utilized in Navigation software to listing the product besides it's designed as a separate widget by passing merchandise (object) of kind List<Product>.

  • Finally, modify the MyHomePage widget’s construct technique to get the product data utilizing Future possibility as a substitute of regular technique name.
Widget construct(BuildContext context) { 
   return Scaffold(
      appBar: AppBar(title: Text("Product Navigation")),
      physique: Center(
         baby: FutureBuilder<List<Product>>(
            future: merchandise, builder: (context, snapshot) , 
         ), 
      )
   ); 
}

 

  • Here observe that we used FutureBuilder widget to render the widget. FutureBuilder will attempt to fetch the info from it’s future property (of kind Future<List<Product>>). If future property returns knowledge, it'll render the widget utilizing ProductFieldList, in any other case throws an error.
  • The full code of the primary.dart is as follows −
import 'bundle:flutter/materials.dart'; 
import 'dart:async'; 
import 'dart:convert'; 
import 'bundle:http/http.dart' as http; 
import 'Product.dart'; 

void essential() => runApp(MyApp(merchandise: fetchProducts())); 

List<Product> parseProducts(String responseBody)  
   ultimate parsed = json.decode(responseBody).solid<Map<String, dynamic>>(); 
   return parsed.map<Product>((json) => Product.fromMap(json)).toList(); 
 
Future<List<Product>> fetchProducts() async { 
   ultimate response = await http.get('http://192.168.1.2:8000/products.json'); 
   if (response.statusCode == 200)  
      return parseProducts(response.physique); 
    else  
      throw Exception('Unable to fetch merchandise from the REST API'); 
    
}
class MyApp extends Statemuch lessWidget {
   ultimate Future<List<Product>> merchandise; 
   MyApp(Key key, this.merchandise) : tremendous(key: key); 
   
   // This widget is the basis of your software. 
   @override 
   Widget construct(BuildContext context) 
      return MaterialApp(
         title: 'Flutter Demo', 
         theme: ThemeData( 
            primarySwatch: Colors.blue, 
         ), 
         house: MyHomePage(title: 'Product Navigation demo house web page', merchandise: merchandise), 
      ); 
   
}
class MyHomePage extends Statemuch lessWidget { 
   ultimate String title; 
   ultimate Future<List<Product>> merchandise; 
   MyHomePage() : tremendous(key: key); 
   
   // ultimate objects = Product.getProducts();
   @override 
   Widget construct(BuildContext context) { 
      return Scaffold(
         appBar: AppBar(title: Text("Product Navigation")), 
         physique: Center(
            baby: FutureBuilder<List<Product>>(
               future: merchandise, builder: (context, snapshot) ,
            ),
         )
      );
   }
}
class ProductFieldList extends Statemuch lessWidget {
   ultimate List<Product> objects; 
   ProductFieldList(); 
   
   @override 
   Widget construct(BuildContext context) {
      return ListView.builder(
         itemCount: objects.size, 
         itemBuilder: (context, index) { 
            return GestureDetector( 
               baby: ProductField(merchandise: objects[index]), 
               onTap: ()  
                  Navigator.push(
                     context, MaterialsPageRoute( 
                        builder: (context) => ProductPage(merchandise: objects[index]), 
                     ), 
                  ); 
               , 
            ); 
         }, 
      ); 
   } 
} 
class ProductPage extends Statemuch lessWidget { 
   ProductPage(Key key, this.merchandise) : tremendous(key: key); 
   ultimate Product merchandise; 
   @override 
   Widget construct(BuildContext context) 
      return Scaffold(
         appBar: AppBar(title: Text(this.merchandise.title),), 
         physique: Center( 
            baby: Container(
               padding: EdgeInunits.all(0), 
               baby: Column( 
                  mainAxisAlignment: MainAxisAlignment.begin, 
                  crossAxisAlignment: CrossAxisAlignment.begin, 
                  youngsters: <Widget>[
                     Image.asset("assets/appimages/" + this.item.image), 
                     Expanded( 
                        child: Container( 
                           padding: EdgeInsets.all(5), 
                           child: Column( 
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                              children: <Widget>[ 
                                 Text(this.item.name, style: 
                                    TextStyle(fontWeight: FontWeight.bold)), 
                                 Text(this.item.description), 
                                 Text("Price: " + this.item.price.toString()), 
                                 RatingBox(), 
                              ], 
                           )
                        )
                     ) 
                  ]
               ), 
            ), 
         ), 
      ); 
    
}
class RatingBox extends StatefulWidget { 
   @override 
   _RatingBoxState createState() =>_RatingBoxState(); 
} 
class _RatingBoxState extends State<RatingBox> { 
   int _rating = 0; 
   void _setRatingAsOne() {
      setState(() { 
         _rating = 1; 
      }); 
   }
   void _setRatingAsTwo() {
      setState(() {
         _rating = 2; 
      }); 
   }
   void _setRatingAsThree() { 
      setState(() {
         _rating = 3; 
      }); 
   }
   Widget construct(BuildContext context) 
      double _size = 20; 
      print(_rating); 
      return Row(
         mainAxisAlignment: MainAxisAlignment.finish, 
         crossAxisAlignment: CrossAxisAlignment.finish, 
         mainAxisSize: MainAxisSize.max, 
         
         youngsters: <Widget>[
            Container(
               padding: EdgeInsets.all(0), 
               child: IconButton( 
                  icon: (
                     _rating >= 1 
                     ? Icon(Icons.star, ize: _size,) 
                     : Icon(Icons.star_border, size: _size,)
                  ), 
                  color: Colors.red[500], onPressed: _setRatingAsOne, iconSize: _size, 
               ), 
            ), 
            Container(
               padding: EdgeInunits.all(0), 
               baby: IconButton(
                  icon: (
                     _rating >= 2 
                     ? Icon(Icons.star, measurement: _size,) 
                     : Icon(Icons.star_border, measurement: _size, )
                  ), 
                  shade: Colors.purple[500], 
                  onPressed: _setRatingAsTwo, 
                  iconSize: _size, 
               ), 
            ), 
            Container(
               padding: EdgeInunits.all(0), 
               baby: IconButton(
                  icon: (
                     _rating >= 3 ? 
                     Icon(Icons.star, measurement: _size,)
                     : Icon(Icons.star_border, measurement: _size,)
                  ), 
                  shade: Colors.purple[500], 
                  onPressed: _setRatingAsThree, 
                  iconSize: _size, 
               ), 
            ), 
         ], 
      ); 
    
}
class ProductField extends Statemuch lessWidget {
   ProductField(Key key, this.merchandise) : tremendous(key: key); 
   ultimate Product merchandise; 
   
   Widget construct(BuildContext context) 
      return Container(
         padding: EdgeInunits.all(2), peak: 140, 
         baby: Card(
            baby: Row( 
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               youngsters: <Widget>[
                  Image.asset("assets/appimages/" + this.item.image), 
                  Expanded( 
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(this.item.name, style:TextStyle(fontWeight: FontWeight.bold)), 
                              Text(this.item.description), 
                              Text("Price: " + this.item.price.toString()), 
                              RatingBox(), 
                           ], 
                        )
                     )
                  )
               ]
            ), 
         )
      ); 
    
}