iosflutterdartcross-platform

A call to API in Flutter doesn't load the required JSON the first time app is loaded


I was recently learning to code in flutter and was building an app using it on iOS. Therefore, I wanted to build one with the NASA APOD API involved in it.

I have created a simple UI and set a card with Image view which will load the image after passing the url from the API's JSON.

The JSON:

{
"copyright": "Panther Observatory", 
"date": "2006-04-15", 
"explanation": "In this stunning cosmic vista, galaxy M81 is on the left surrounded by blue spiral arms.  On the right marked by massive gas and dust clouds, is M82.  These two mammoth galaxies have been locked in gravitational combat for the past billion years.   The gravity from each galaxy dramatically affects the other during each hundred million-year pass.  Last go-round, M82's gravity likely raised density waves rippling around M81, resulting in the richness of M81's spiral arms.  But M81 left M82 with violent star forming regions and colliding gas clouds so energetic the galaxy glows in X-rays.  In a few billion years only one galaxy will remain.", 
"hdurl": "https://apod.nasa.gov/apod/image/0604/M81_M82_schedler_c80.jpg", 
"media_type": "image", 
"service_version": "v1", 
"title": "Galaxy Wars: M81 versus M82", 
"url": "https://apod.nasa.gov/apod/image/0604/M81_M82_schedler_c25.jpg" },

Now I get the URL from this JSON and convert it to a string and pass it to the Image.Network function.

When I run the app the first time. The image doesn't load and throws me an errorenter image description here

Well but after I hit the Refresh button on the Visual Studio Code debugger console enter image description here

The code will run and give me the desired output.enter image description here

So the problem is first time the app is loaded it always throws an error saying that the url is not defined, but after refreshing the app the image and all the data loads from the API call.
What could be the error in this situation. I think it is something that is related to the state on Flutter. Any help is appreciated.!!

Here is the code

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

class Home extends StatefulWidget {
  @override
  StateApodCall createState() => new StateApodCall();
}

class StateApodCall extends State<Home> {
  final url = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY";
  List resBody;
  String imageUrl;
  String imageTitle;

  Future<String> getAPODData() async{
    var res = await http
    .get(Uri.encodeFull(url), headers: {"Accept": "application/json"});

    var resBody = json.decode(res.body);
    print(resBody);
    print(resBody["copyright"]);
    imageUrl = resBody["hdurl"];
    imageTitle = resBody["title"];
    print(imageUrl);
    return "Success!!";
  }

  @override
  initState() {
    super.initState();
    this.getAPODData();
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      decoration: new BoxDecoration(
        gradient: new LinearGradient(
          colors: [
            const Color(0xFF1ca2e3),
            const Color(0xFF1450a3)
          ],
          begin: const FractionalOffset(1.0, 0.5),
          end: const FractionalOffset(0.3, 0.1),
          stops: [0.0, 0.5],
          tileMode: TileMode.clamp
        ),
      ),
      child: new Scaffold(
        backgroundColor: Colors.transparent,
        appBar: new AppBar(
          backgroundColor: const Color(0xFF124489),
          elevation: 20.0,
          leading: new IconButton(
            icon: new Icon(Icons.menu),
            onPressed: () {

            }
          ),
          title: new Text(
            "APOD",
            style: const TextStyle(
              color: Colors.white,
              fontFamily: 'Poppins',
              fontWeight: FontWeight.w600,
              fontSize: 34.0
              ),
            ),
        ),
        body: new ListView(
          children : [
            new Card(
              elevation: 3.0,
              child: new Column(
                children: [
                  new Image.network(
                    imageUrl,
                    width: double.infinity,
                    fit: BoxFit.fitWidth,
                  ),
                ],
              ),
            ),
            new Card(
              elevation: 2.0,
              child: new Text(imageTitle),
            ),
          ],
        ),
      )
    );
  }
}

Solution

  • To solve I added this code in the body of the nested statement!

    body: imageUrl != null ? new ListView(
          children: [
              new Card(
                elevation: 3.0,
                child: new Column(
                  children: [
                    new Image.network(
                      imageUrl,
                      width: double.infinity,
                      fit: BoxFit.fitWidth,
                    ),
                  ],
                ),
              ),
              new Card(
                elevation: 2.0,
                child: new Text(imageTitle),
              )
            ],
        ) : new Center(child:new CircularProgressIndicator(
          strokeWidth: 3.0,
        )),
    

    and also included the setState function

    this.setState((){
      resBody = json.decode(res.body);
      imageUrl = resBody["hdurl"];
      imageTitle = resBody["title"];
    });