EXPERIMENT-9

 9a)Fetch data from a REST API.

We have a lot of ways to show data in our app:

  • Static Data
  • From a file
  • And another form is from a database or public APIs.

The most popularly used form is from Database or Public APIs.

  • An API (Application Programming Interface) is a set of rules and protocols that allows different software applications to communicate and interact with each other. 
  • In simpler terms, an API is like a menu in a restaurant: it tells you what you can order (available functions), how to order it (the request format), and what you will get back (the response). This allows developers to use functionalities of other software or services without needing to understand their internal workings.
  • REST API enables communication between client and server over HTTP by exposing resources via URLs and allowing operations on these resources using standard HTTP methods. It is widely used for building web services and mobile app backends.




How do APIs Work?




A user application can contact any database through HTTP requests. So, we can create GET, POST, PUT, or DELETE HTTP requests to a database. In return, the database sends us data or results or responses in form of JSON or HTML or XML. The JSON format is widely used. We then parse the JSON into a proper model class and use it in our app.

Define the API Endpoint

The URL of the REST API is defined as:

https://official-joke-api.appspot.com/random_joke

This endpoint returns a random joke as a resource.

Create the URI Object

The URL string is parsed into a Uri object using Uri.parse(), which is required by the HTTP package.


Send an HTTP GET Request

Using http.get(url), the code sends a GET request to the API endpoint to retrieve the joke resource.


Await the Response

The program waits asynchronously for the server to respond.


Check Response Status Code

The response’s HTTP status code is checked to ensure the request was successful (200 OK).


Parse JSON Response

If successful, the response body, which is a JSON string, is decoded into a Dart map using jsonDecode(response.body).


Extract Data from JSON

Specific fields (setup and punchline) are accessed from the decoded JSON object.


Output the Data

The joke setup and punchline are printed to the console.


Handle Errors

If the status code is not 200, an error message is printed. Additionally, any exceptions thrown during the HTTP request or JSON parsing are caught and logged.

Summary

The program asks a website for a random joke.

It waits for the response.

If successful, it converts the JSON data into Dart objects.

It prints the joke parts.

If anything goes wrong, it prints an error message.

import 'dart:convert';

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

void main() async {

  final url = Uri.parse('https://official-joke-api.appspot.com/random_joke');

 try {

    final response = await http.get(url);


    if (response.statusCode == 200) {

      final joke = jsonDecode(response.body);

      print('Here is a random joke:');

      print('${joke['setup']}');

      print('${joke['punchline']}');

    } else {

      print('Failed to fetch joke. Status code: ${response.statusCode}');

    }

  } catch (e) {

    print('Error: $e');

  }

}

What the code does:

The program fetches a random joke from an online service (a REST API) and prints the joke to the console.

import 'dart:convert';

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

  • dart:convert is a built-in Dart library that helps us convert data formats, like turning JSON text into Dart objects.
  • package:http/http.dart is an external library that helps us make HTTP requests (like asking a website for data). We give it a nickname http for easy use.


void main() async {

main function: This is where the program starts running.

async keyword: Means the function can do things that take time (like waiting for a website to respond) without freezing the whole program.


  final url = Uri.parse('https://official-joke-api.appspot.com/random_joke');

We create a variable called url that stores the address (URL) of the joke service.

Uri.parse converts the URL string into a format the program can understand for making a request.


  try {

We start a try block. This means: "Try to do the code inside here, but if something goes wrong, we will catch the error."


    final response = await http.get(url);

We ask (make a GET request) the joke website (url) to send us some data.

The await keyword means: "Wait here until the website sends back the data."

The result from the website is stored in the variable response


    if (response.statusCode == 200) {

We check if the website said "OK" by looking at the status code.

200 means the request was successful and the website sent back the data we asked for.


      final joke = jsonDecode(response.body);

response.body contains the data sent by the website, but it is in JSON format (a text format used to share data).

jsonDecode converts this JSON text into a Dart object (a map/dictionary).

We store this Dart object in a variable called joke.


      print('Here is a random joke:');

      print('${joke['setup']}');

      print('${joke['punchline']}');


We print some messages to the console.

joke['setup'] gets the first part of the joke (the setup).

joke['punchline'] gets the second part (the punchline).

The ${} syntax means "insert this value into the string."


    } else {

      print('Failed to fetch joke. Status code: ${response.statusCode}');

    }

If the status code was not 200, it means something went wrong.

We print an error message showing the status code.


  } catch (e) {

    print('Error: $e');

  }

}

If any error happens during the request or decoding, the catch block runs.

We print the error message, so we know what went wrong.


9b) Display the fetched data in a meaningful way in the UI.


What this app does:

When you open the app, it fetches a random joke from a website.

It shows a loading spinner while waiting.

It displays the joke (two parts: setup and punchline) when data arrives.

If something goes wrong, it shows an error message.

You can tap the refresh button to get a new joke.


import 'dart:convert';

import 'package:flutter/material.dart';

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


void main() => runApp(MaterialApp(home: JokePage()));


class JokePage extends StatefulWidget {

  @override

  _JokePageState createState() => _JokePageState();

}


class _JokePageState extends State<JokePage> {

  String? setup, punchline, error;

  bool loading = false;


  Future<void> fetchJoke() async {

    setState(() {

      loading = true;

      error = null;

    });

    try {

      final res = await http.get(Uri.parse('https://official-joke-api.appspot.com/random_joke'));

      if (res.statusCode == 200) {

        final data = jsonDecode(res.body);

        setState(() {

          setup = data['setup'];

          punchline = data['punchline'];

          loading = false;

        });

      } else {

        setState(() {

          error = 'Error: ${res.statusCode}';

          loading = false;

        });

      }

    } catch (e) {

      setState(() {

        error = 'Failed to fetch joke';

        loading = false;

      });

    }

  }


  @override

  void initState() {

    super.initState();

    fetchJoke();

  }


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Random Joke')),

      body: Center(

        child: loading

            ? CircularProgressIndicator()

            : error != null

                ? Text(error!)

                : Column(

                    mainAxisSize: MainAxisSize.min,

                    children: [

                      Text(setup ?? '', style: TextStyle(fontSize: 20,color: Colors.blue, fontWeight: FontWeight.bold), textAlign: TextAlign.center),

                      SizedBox(height: 10),

                      Text(punchline ?? '', style: TextStyle(fontSize: 18,color: Colors.red), textAlign: TextAlign.center),

                    ],

                  ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: fetchJoke,

        child: Icon(Icons.refresh),

      ),

    );

  }

}




import 'dart:convert';

import 'package:flutter/material.dart';

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


Imports:

dart:convert: Helps convert data formats, like JSON text to Dart objects.

flutter/material.dart: Provides Flutter's UI components.

http: Lets us make HTTP requests to get data from the internet.


class _JokePageState extends State<JokePage> {

  String? setup, punchline, error;

  bool loading = false;

Variables to hold:

setup and punchline: parts of the joke.

error: error message if fetching fails.

loading: whether the app is currently loading data.


  Future<void> fetchJoke() async {

    setState(() {

      loading = true;

      error = null;

    });

fetchJoke() is a function that gets a joke from the internet.

async means it can wait for slow operations (like network calls).

setState() tells Flutter to update the UI — here, we show loading and clear errors.


    try {

      final res = await http.get(Uri.parse('https://official-joke-api.appspot.com/random_joke'));

We send an HTTP GET request to the joke API URL.

await pauses here until the response arrives.

res holds the response from the server.


      if (res.statusCode == 200) {

        final data = jsonDecode(res.body);

        setState(() {

          setup = data['setup'];

          punchline = data['punchline'];

          loading = false;

        });

Check if the server responded with status code 200 (means success).

res.body is the data returned, still as a JSON text string.

jsonDecode() converts this JSON text into a Dart object (a Map).

Extract setup and punchline from this object.

Use setState() again to update the UI with the joke and hide loading.


      } else {

        setState(() {

          error = 'Error: ${res.statusCode}';

          loading = false;

        });

      }

If status code is not 200, something went wrong.

Show an error message with the status code.


    } catch (e) {

      setState(() {

        error = 'Failed to fetch joke';

        loading = false;

      });

    }

  }

If any exception happens (like no internet), catch it.

Show a generic error message and stop loading.


  @override

  void initState() {

    super.initState();

    fetchJoke();

  }

initState() runs once when the widget is created.

We call fetchJoke() here so the app starts fetching as soon as it opens.


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Random Joke')),

      body: Center(

        child: loading

            ? CircularProgressIndicator()

            : error != null

                ? Text(error!)

                : Column(

                    mainAxisSize: MainAxisSize.min,

                    children: [

                      Text(setup ?? '', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), textAlign: TextAlign.center),

                      SizedBox(height: 10),

                      Text(punchline ?? '', style: TextStyle(fontSize: 18), textAlign: TextAlign.center),

                    ],

                  ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: fetchJoke,

        child: Icon(Icons.refresh),

      ),

    );

  }

}

UI layout:

Scaffold: Basic app structure with app bar and body.

AppBar: The top bar with the title "Random Joke".

body: Center widget to center content.

If loading is true, show a spinning circle (CircularProgressIndicator).

Else if there's an error, show the error message.

Otherwise, show the joke:

Text for setup in bold.

Some space (SizedBox).

Text for punchline in normal font.

floatingActionButton: A floating button with a refresh icon.

When tapped, it calls fetchJoke() again to load a new joke.




Comments

Popular posts from this blog

EXPERIMENT-3

EXPERIMENT-2

EXPERIMENT-4