Unable to Disable Button in Stateful Widget Until Request has Completed

Issue

I am having problems with a stateful widget in my flutter app which has an accept button to make an http request. I want it to be able to disable the button when pressed until the http request completes, but it doesn’t seem to work when setting the state before the request.

I have put together a demo below with a dummy request method to simulate what is happening. When the button is pressed it isn’t disabled until after the call to _acceptRequest completes. My expectation is for it to disable before that because set state is called before.

There are some examples of this on here, but it is not working for me and I seem to be doing the same thing as suggested on those posts.

import 'package:flutter/material.dart';
import 'dart:io';

class StatefulButtonDisable extends StatefulWidget {
  const StatefulButtonDisable({ Key? key }) : super(key: key);

  @override
  _StatefulButtonDisableState createState() => _StatefulButtonDisableState();
}

class _StatefulButtonDisableState extends State<StatefulButtonDisable> {
  bool _enableButton = true;

  @override
  Widget build(BuildContext context) {
    Future<bool> _acceptRequest(id) async {
      print('accpeting request $id');
      sleep(Duration(seconds: 5));
      return true;
    }

    _sendRequest(id) async {
      setState(() {
       _enableButton = false;
      });
      await _acceptRequest(id);
    }


    return Scaffold(
      appBar: AppBar(
        title: Text('Disable Button'),
      ),
      body: Container(
        child: ElevatedButton(
          onPressed: _enableButton
          ? () { _sendRequest(7); }
          : null,
          child: Text('Press Me'),),
        
      ),
    );
  }
}

Solution

Future<bool> _acceptRequest(id) async {
  print('accpeting request $id');
  sleep(Duration(seconds: 5));
  return true;
}

I know it returns a future and you have marked it as async, but this is not actually an asyncronous function. It does not do anything asynchonously. It does not use the await keyword. The sleep function will just completely block the currect thread, no questions asked, no prisoners taken.

The documentation for sleep says

Use this with care, as no asynchronous operations can be processed in a isolate while it is blocked in a sleep call.

If you want your application to work properly, the method marked async should use a way of waiting in line with the async/await model, for example Future.delayed:

Future<bool> _acceptRequest(id) async {
  print('accpeting request $id');
  await Future.delayed(Duration(seconds: 5));
  return true;
}

Answered By – nvoigt

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published