简体   繁体   中英

How to show progress bar on button click in flutter

I am calling an API on button click but when I click on the button nothing happens. also I want to show a linear progress bar when the user clicks on the button uless/until data gets loaded but it is not working the way I expect it to work. Here is my code. I am a newbie. I am stuck on this problem please someone corrects my code so that it will work the way I expect.


class _MyHomePageState extends State<MyHomePage> {
  getFokatKiAdvice() async {
    final response =
        await http.get(Uri.parse("https://api.adviceslip.com/advice"));
    var resp = json.decode(response.body);
    print(resp);
    return resp['slip']['advice'];
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            children: [
              const Card(
                child: ListTile(
                  title: Text(
                    "Advice for you !",
                    textAlign: TextAlign.center,
                  ),
                ),
              ),
              Card(
                child: Column(
                  children: [
                    ListTile(
                      title: FutureBuilder(
                        future: getFokatKiAdvice(),
                        builder:
                            (BuildContext context, AsyncSnapshot snapshot) {
                          if (snapshot.hasData) {
                            return Text(
                              snapshot.data,
                              textAlign: TextAlign.center,
                            );
                          } else if (snapshot.hasError) {
                            return const Text(
                                "Oye !! Thare pass Internet naahi hn !!");
                          } else {
                            return const LinearProgressIndicator();
                          }
                        },
                      ),
                    ),
                    const SizedBox(
                      height: 5.00,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        getFokatKiAdvice();
                        // setState(() {});
                      },
                      child: const Text("Ghe Advice !"),
                    ),
                    const SizedBox(
                      height: 10,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

You just need to make bool if its loading and getting data, the indicator shows up.

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String data;
  bool _isLoading;
  getFokatKiAdvice() async {
    final response =
        await http.get(Uri.parse("https://api.adviceslip.com/advice"));
    var resp = json.decode(response.body);
    if (response.statusCode != 200) {
      data = "Oye !! Thare pass Internet naahi hn !!";
    }
    print(resp);
    setState(() {
      data = resp['slip']['advice'];
      _isLoading = false;
    });
  }

  @override
  void initState() {
    _isLoading = true;
    getFokatKiAdvice();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              children: [
                const Card(
                  child: ListTile(
                    title: Text(
                      "Advice for you !",
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
                Card(
                  child: Column(
                    children: [
                      ListTile(
                          title: _isLoading
                              ? const LinearProgressIndicator()
                              : Text(
                                  data,
                                  textAlign: TextAlign.center,
                                )),
                      const SizedBox(
                        height: 5.00,
                      ),
                      ElevatedButton(
                        onPressed: () {
                          setState(() {
                            _isLoading = true;
                            data = '';
                          });
                          getFokatKiAdvice();
                        },
                        child: const Text("Ghe Advice !"),
                      ),
                      const SizedBox(
                        height: 10,
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

here is my solution without futureB

here is result

这是结果

you can make a lazyload

class _MyHomePageState extends State<MyHomePage> {
  bool _isLoading= false;

  getFokatKiAdvice() async {
    setState ({
      _isLoading = true;
    });
    try{
     final response =
        await http.get(Uri.parse("https://api.adviceslip.com/advice"));
     var resp = json.decode(response.body);
     print(resp);
     return resp['slip']['advice'];
     setState ({
       _isLoading = false;
     )};
   } catch (e){
     print(e);
     setState ({
       _isLoading = false;
     )};
   }
  }

.......

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      // create condition when loading show indicator progress, else show content
      body:  _isLoading ? Center (child: CircularProgressIndicator()) 
      : Center(
        child: Padding(
       .......
       // other code no change needed

Calling this API with small difference of time, provide same result sometimes. Could be issue on caching, but don't know for sure. Adding little delay works find. or checking the current data with previous also make sure not to get duplicate data.

Also use a future variable instead of calling directly inside future.

String? _currentData, newData;
Future<String?> getFokatKiAdvice() async {
  do {
    await Future.delayed(const Duration(
        milliseconds:
            100)); // have more loading you can ignore this, but it will call multiple times
    newData = await fetchFromApi();
  } while (newData == _currentData);

  _currentData = newData;
  return newData;
}

And on

title: FutureBuilder(
  future: _future,

Now to recall the api

ElevatedButton(
  onPressed: () {
    setState(() {
      _future = getFokatKiAdvice();
    });
  },

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM