update get query data every 20 sec in flutter

Question

Asked by Andrii H on November 24, 2021 (source).

I have a page, on this page I show data cards. I receive this data on request(getTaskDetails). I get an array of data and show this data on the cards. But the problem is that I want to make these queries every 20 seconds. That the data which will be on my page are updated. Here is my code:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import  'package:uhf_scan/model/setting/globalvar.dart' as global;
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:uhf_scan/model/PageUhf/PageUhf.dart';
import 'package:qrscan/qrscan.dart' as scanner;
import 'package:flutter/services.dart';
 class TaskList extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: TaskListParse(),

    );
  }

}
class TaskListParse extends StatefulWidget {
  TaskListParse() : super();
  @override
  _JsonParseObjectsTask createState() => _JsonParseObjectsTask();
}

class _JsonParseObjectsTask extends State <StatefulWidget> {
  String limit = global.limit.toString();
  List<TaskDetails> _searchResult = [];
  List<TaskDetails> _taskDetails = [];
  List<TaskDetails> _taskBarcode = [];
  TextEditingController controller = new TextEditingController();

  String? _mySeals;
  
  Future<Null> getTaskDetails() async {

    final String url = global.urlVar ;

    HttpClient client = new HttpClient();

    client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
    
    final request = await client
        .getUrl(Uri.parse(url))
        .timeout(Duration(seconds: 5));

    HttpClientResponse response = await request.close();
    
    var responseBody = await response.transform(utf8.decoder).join();
    
    final responseJson = json.decode(responseBody);
    if (200 == response.statusCode) {
      setState(() {
        for (Map<String,dynamic> user in responseJson) {
          _taskDetails.add(TaskDetails.fromJson(user));
        }
      });
    }
  }

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

    getTaskDetails();
  }

  Widget _buildUsersList() {
    return new ListView.builder(
      itemCount: _taskDetails.length,
      itemBuilder: (context, index) {
        return new Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15.0),
          ),
          color: Colors.white38,
          margin: EdgeInsets.symmetric(vertical: 7),
          child: ListTile(
              title: Text(
                _taskDetails[index].name,
                style: TextStyle(fontSize: 15,
                  color: Colors.black)
              ),
              leading: FaIcon(FontAwesomeIcons.truck),
              onTap: () =>
              {
                  global.taskId =  _taskDetails[index].id,
                  global.taskName =  _taskDetails[index].name,
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ScanUhf()),
                )
              }
          ),
        );
      },
    );
  }

  Widget _buildSearchResults() {
    return new ListView.builder(
      itemCount: _searchResult.length,
      itemBuilder: (context, i) {
        return new Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15.0),
          ),
          color: Colors.white38,
          margin: EdgeInsets.symmetric(vertical: 7),
          child: ListTile(
              title: Text(
                _searchResult[i].name,
                style: TextStyle(fontSize: 15),
              ),
              leading: Icon(
                Icons.home_outlined,
                size: 30,
                color: Colors.black87,
              ),
              onTap: () =>
              {
                global.taskId =  _searchResult[i].id,
                global.taskName =  _searchResult[i].name,
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ScanUhf()),
                )
              }
          ),
        );
      },
    );
  }

  Widget _buildSearchBox() {

    return new Container(
      color: Colors.blueGrey,
      padding: const EdgeInsets.all(8.0),
      child: new Card(
        margin: EdgeInsets.symmetric(vertical: 7),
        child: new ListTile(
          leading: new Icon(Icons.search),
          title: new TextField(
            controller: controller,
            decoration: new InputDecoration(
                hintText: 'Пошук', border: InputBorder.none),
            onChanged: onSearchTextChanged,
          ),
          trailing: new IconButton(
            icon: new Icon(Icons.cancel),
            onPressed: () {
              controller.clear();
              onSearchTextChanged('');
            },
          ),
        ),
      ),
    );
  }

  Widget _buildBody() {

    return new Scaffold(
      body:Container(
        child:Column(
          children: <Widget>[
            new Container(
                color: Theme.of(context).primaryColor, child: _buildSearchBox()),
            new Expanded(
                child: _searchResult.length != 0 || controller.text.isNotEmpty
                    ? _buildSearchResults()
                    : _buildUsersList()),
          ],
        ),

      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _scanQR();
          });
        },
        child: const Icon(Icons.qr_code_scanner_sharp),
        backgroundColor: Colors.pink,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: _buildBody()
    );
  }

  onSearchTextChanged(String text) async {
    _searchResult.clear();
    if (text.isEmpty) {
      setState(() {});
      return;
    }

    _taskDetails.forEach((userDetail) {
      if (userDetail.name.toLowerCase().contains(text.toLowerCase()))
        _searchResult.add(userDetail);
    });

    setState(() {});
  }

  Future _scanQR () async {
    try {
     String? cameraScanResult = await scanner.scan();
      setState(() {
       _mySeals = cameraScanResult; // setting string result with cameraScanResult
      });
    } on PlatformException catch (e) {
      print(e);
    }
  }
}

class TaskDetails {

  final String  id, name;
  
  TaskDetails({required this.id,required this.name});

  factory TaskDetails.fromJson(Map<String, dynamic> json) {
    return new TaskDetails(
      id: json['id'],
      name: json['name']
    );
  }
}

Everything works as it should. But to update the data, I need to go to the page again. And I want to update this data by staying on the page. I will be grateful for the help)

Answer

Question answered by Suvash B (source).

In your initstate method you can initiate a timer which gets fired every 20 seconds and calls your callback function as:

Timer.periodic(Duration(seconds: 20),(_) => getTaskDetails())

Now your getTastDetails() function will get called every 20 seconds and the data will be updated. And dont forget to cancel the timer in dispose method. I've modified your code to work as you expected!

    import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import  'package:uhf_scan/model/setting/globalvar.dart' as global;
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:uhf_scan/model/PageUhf/PageUhf.dart';
import 'package:qrscan/qrscan.dart' as scanner;
import 'package:flutter/services.dart';
class TaskList extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: TaskListParse(),

    );
  }

}
class TaskListParse extends StatefulWidget {
  TaskListParse() : super();
  @override
  _JsonParseObjectsTask createState() => _JsonParseObjectsTask();
}

class _JsonParseObjectsTask extends State <StatefulWidget> {
  String limit = global.limit.toString();
  List<TaskDetails> _searchResult = [];
  List<TaskDetails> _taskDetails = [];
  List<TaskDetails> _taskBarcode = [];
  TextEditingController controller = new TextEditingController();

  String? _mySeals;

  Future<Null> getTaskDetails() async {

    final String url = global.urlVar ;

    HttpClient client = new HttpClient();

    client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);

    final request = await client
        .getUrl(Uri.parse(url))
        .timeout(Duration(seconds: 5));

    HttpClientResponse response = await request.close();

    var responseBody = await response.transform(utf8.decoder).join();

    final responseJson = json.decode(responseBody);
    if (200 == response.statusCode) {
      _taskDetails.clear();
      setState(() {
        for (Map<String,dynamic> user in responseJson) {
          _taskDetails.add(TaskDetails.fromJson(user));
        }
      });
    }
  }
  late Timer _timer;
  @override
  void initState() {
    _timer = Timer.periodic(Duration(seconds: 20),(_) => getTaskDetails());
    super.initState();
  }

  @override
  void dispose(){
    _timer.cancel();
    super.dispose();
  }

  Widget _buildUsersList() {
    return new ListView.builder(
      itemCount: _taskDetails.length,
      itemBuilder: (context, index) {
        return new Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15.0),
          ),
          color: Colors.white38,
          margin: EdgeInsets.symmetric(vertical: 7),
          child: ListTile(
              title: Text(
                  _taskDetails[index].name,
                  style: TextStyle(fontSize: 15,
                      color: Colors.black)
              ),
              leading: FaIcon(FontAwesomeIcons.truck),
              onTap: () =>
              {
                global.taskId =  _taskDetails[index].id,
                global.taskName =  _taskDetails[index].name,
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ScanUhf()),
                )
              }
          ),
        );
      },
    );
  }

  Widget _buildSearchResults() {
    return new ListView.builder(
      itemCount: _searchResult.length,
      itemBuilder: (context, i) {
        return new Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(15.0),
          ),
          color: Colors.white38,
          margin: EdgeInsets.symmetric(vertical: 7),
          child: ListTile(
              title: Text(
                _searchResult[i].name,
                style: TextStyle(fontSize: 15),
              ),
              leading: Icon(
                Icons.home_outlined,
                size: 30,
                color: Colors.black87,
              ),
              onTap: () =>
              {
                global.taskId =  _searchResult[i].id,
                global.taskName =  _searchResult[i].name,
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ScanUhf()),
                )
              }
          ),
        );
      },
    );
  }

  Widget _buildSearchBox() {

    return new Container(
      color: Colors.blueGrey,
      padding: const EdgeInsets.all(8.0),
      child: new Card(
        margin: EdgeInsets.symmetric(vertical: 7),
        child: new ListTile(
          leading: new Icon(Icons.search),
          title: new TextField(
            controller: controller,
            decoration: new InputDecoration(
                hintText: 'Пошук', border: InputBorder.none),
            onChanged: onSearchTextChanged,
          ),
          trailing: new IconButton(
            icon: new Icon(Icons.cancel),
            onPressed: () {
              controller.clear();
              onSearchTextChanged('');
            },
          ),
        ),
      ),
    );
  }

  Widget _buildBody() {

    return new Scaffold(
      body:Container(
        child:Column(
          children: <Widget>[
            new Container(
                color: Theme.of(context).primaryColor, child: _buildSearchBox()),
            new Expanded(
                child: _searchResult.length != 0 || controller.text.isNotEmpty
                    ? _buildSearchResults()
                    : _buildUsersList()),
          ],
        ),

      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _scanQR();
          });
        },
        child: const Icon(Icons.qr_code_scanner_sharp),
        backgroundColor: Colors.pink,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: _buildBody()
    );
  }

  onSearchTextChanged(String text) async {
    _searchResult.clear();
    if (text.isEmpty) {
      setState(() {});
      return;
    }

    _taskDetails.forEach((userDetail) {
      if (userDetail.name.toLowerCase().contains(text.toLowerCase()))
        _searchResult.add(userDetail);
    });

    setState(() {});
  }

  Future _scanQR () async {
    try {
      String? cameraScanResult = await scanner.scan();
      setState(() {
        _mySeals = cameraScanResult; // setting string result with cameraScanResult
      });
    } on PlatformException catch (e) {
      print(e);
    }
  }
}

class TaskDetails {

  final String  id, name;

  TaskDetails({required this.id,required this.name});

  factory TaskDetails.fromJson(Map<String, dynamic> json) {
    return new TaskDetails(
        id: json['id'],
        name: json['name']
    );
  }
}
DART FLUTTER
SHARE: