0

I have an app for showing world times. I have a page for changing different locations around the world. It's a ListView.

Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: colorOne,
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: Text("Change location"),
        centerTitle: true,
        elevation: 0.0,
      ),
      body: ListView.builder(
        physics: const AlwaysScrollableScrollPhysics(),
        padding: EdgeInsets.fromLTRB(5, 10, 5, 0),
        itemCount: locations.length,
        itemBuilder: (context, index) {
          return Card(
            child: ListTile(
              onTap: () {
                updateTime(index);
               ... rest code

As you can see, when I tap on ListTIle, it calls updateTime function

updateTime function:

void updateTime(index) async {
    WorldTime instance = locations[index];
    await instance.getTime();
    Navigator.pop(context, {
      "location": instance.location,
      "flag": instance.flag,
      "time": instance.time,
      "date": instance.date,
      "isDayTime": instance.isDayTime,
    });
    // obtain shared preferences
    final savingLastLocation = await SharedPreferences.getInstance();

    // set value
    savingLastLocation.setString("location", instance.location);
    savingLastLocation.setString("url", instance.url);
    savingLastLocation.setString("flag", instance.flag);
}

If user starts spamming on tiles while awaiting for that function, app will either show full blank grey screen or drop red screen of death saying "boolean expression must be null".

How can I add some kind of loading screen/widget or prevent calling function again if it's already called once?

hata
  • 11,633
  • 6
  • 46
  • 69
x24dsa
  • 17
  • 1
  • 5

2 Answers2

3

You can wrap your screen with IgnorePointer, which ignores any click.

Create bool variable.

bool ignore = false;
bool methodcalled = false; // new added line variable

Now wrap your scaffold with IgnorePointer.

return IgnorePointer(
      ignoring: ignore,
      child: Scaffold(

now, set ignore variable to true when user tap on any item.

onTap: () {
        setState(() {
                  ignore = true;
         });
        updateTime(index).then((_){
             setState(() {
                  ignore = false;
             });
        });
       .... rest code

Add return in your method.

 return 1


 void updateTime(index) async {
 if(!methodcalled){
    methodcalled = !methodcalled;
 }else{
    return 0;
 }

WorldTime instance = locations[index];
await instance.getTime();
Navigator.pop(context, {
  "location": instance.location,
  "flag": instance.flag,
  "time": instance.time,
  "date": instance.date,
  "isDayTime": instance.isDayTime,
});
// obtain shared preferences
final savingLastLocation = await SharedPreferences.getInstance();

// set value
savingLastLocation.setString("location", instance.location);
savingLastLocation.setString("url", instance.url);
savingLastLocation.setString("flag", instance.flag);
methodcalled = !methodcalled;  // added line 
return 1; // added line
}
Viren V Varasadiya
  • 25,492
  • 9
  • 45
  • 61
  • I can't use .then() on updateTime(index). It says: "The expression here has a type of 'void', and therefore can't be used." If I remove "void" from my function I get this exception in debug console "type '() => Null' is not a subtype of type '(dynamic) => FutureOr' of 'f'". If I start spamming on Tile again, app crashes again showing black screen – x24dsa Apr 30 '20 at 13:12
  • just add return keyword in function and make then method like following. then((_){. i also updated my answer look into it. @v4yne1 – Viren V Varasadiya Apr 30 '20 at 13:14
  • Thanks! Exception is now gone but still, if I double tap quickly, app shows full black screen and I have to restart it – x24dsa Apr 30 '20 at 13:21
0

onPressed set like this

onPressed: () async {
                dynamic result =
                    await Navigator.pushNamed(context, '/location');
                if (result != null) {
                  setState(() {
                    data = {
                      'location': result['location'],
                      'flag': result['flag'],
                      'time': result['time'],
                      'isDateTime': result['isDateTime']
                    };
                  });
                }
              },
Anil Kumar
  • 1,830
  • 15
  • 24