Irfan Ganatra
Irfan Ganatra

Reputation: 1398

can't see circularprogressindicator while getting data from api in flutter

I am trying to show data from api and while loading data , there should be shown a circularprogressindicator,

but when I start app..it directly showing data instead of circularprogressindicator


class _HomeScreenState extends State<HomeScreen> {
  bool isloading = false;
  var maplist ;
  Future<void> fetchdata() async {

   setState(() {
     isloading=true;
   });
    var resp =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    maplist = json.decode(resp.body);
   setState(() {
      isloading = false;
       });
  }
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    fetchdata();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      body: MyBody(),
    ));
  }

  MyBody() {
    return isloading==true ? Center(child: CircularProgressIndicator()) : ListView.builder(
        itemCount: maplist.length,
        itemBuilder: (context,index){
          return Container(
            padding: EdgeInsets.all(8.0),
              
              child: Text(maplist[index]['title']));
        });
  }
}

Upvotes: 0

Views: 105

Answers (5)

eamirho3ein
eamirho3ein

Reputation: 17950

You need to use FutureBuilder, it is not good to use async function in initState, try this:

FutureBuilder<List<Map<String,dynamic>>>(
        future: fetchdata(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return Center(child: CircularProgressIndicator());
            default:
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                List<Map<String,dynamic>> data = snapshot.data ?? [];

                return ListView.builder(
                    itemCount: data.length,
                    itemBuilder: (context, index) {
                      return Container(
                          padding: EdgeInsets.all(8.0),
                          child: Text(data[index]['title']));
                    });
              }
          }
        },
      ),

also you need to change your fetchdata to this:

Future<List<Map<String,dynamic>>> fetchdata() async {
    var resp =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    return json.decode(resp.body);
  }

Upvotes: 1

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63829

It's actually working perfectly fine, it shows too fast because it is receiving data quickly(+ could be cache case).

If you like to have more delay you can add, future.delay which is unnecessary

  Future<void> fetchdata() async {
    setState(() {
      isloading = true;
    });
    var resp =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    maplist = json.decode(resp.body);
    // get more delay
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      isloading = false;
    });
  }

A better of way of handling future method with FutureBuilder

Upvotes: 1

My Car
My Car

Reputation: 4566

Try the following code:

class _HomeScreenState extends State<HomeScreen> {
  var maplist;
  Future<void> fetchdata() async {
    var resp =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    setState(() {
      maplist = json.decode(resp.body);
    }
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      body: MyBody(),
    ));
  }

  MyBody() {
    return FutureBuilder(
      future: fetchdata(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const CircularProgressIndicator();
        }

        return ListView.builder(
        itemCount: maplist.length,
        itemBuilder: (context,index){
          return Container(
            padding: EdgeInsets.all(8.0),
              
              child: Text(maplist[index]['title']));
        });
      }
  }
}

Upvotes: 1

Deniz Durmaz
Deniz Durmaz

Reputation: 85

You can use like that

import 'dart:convert';

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

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  bool isloading = false;
  var maplist;
  Future<void> fetchdata() async {
    setState(() {
      isloading = true;
    });
    var resp = await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    maplist = json.decode(resp.body);

    setState(() {
      isloading = false;
    });
  }

  @override
  void initState() {
    super.initState();
    fetchdata();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: isloading ? const CircularProgressIndicator() : const MyBody(),
    );
  }
}

class MyBody extends StatelessWidget {
  const MyBody({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      //Write your code here
    );
  }
}

Upvotes: 0

Jasmin Sojitra
Jasmin Sojitra

Reputation: 1299

Try this one,set isloading default true

class _HomeScreenState extends State<HomeScreen> {
  bool isloading = true;
  var maplist ;
  Future<void> fetchdata() async {

    var resp =
        await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    maplist = json.decode(resp.body);
   setState(() {
      isloading = false;
       });
  }
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    fetchdata();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      body: MyBody(),
    ));
  }

  MyBody() {
    return isloading ? Center(child: CircularProgressIndicator()) : ListView.builder(
        itemCount: maplist.length,
        itemBuilder: (context,index){
          return Container(
            padding: EdgeInsets.all(8.0),
              
              child: Text(maplist[index]['title']));
        });
  }
}

Upvotes: 0

Related Questions