2

I need to show a progress bar like below :

download or upload progress bar

I have implemented it this way but the value inside the progress bar is not updated :

  1. use upload() function to simulate file upload by submitting a test POST request
  2. use StatefulBuilder() for convert my dialog from stateless to statefull

my code :

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

void main() => runApp(const MaterialApp(
      home: MyApp(),
    ));

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String status = "loading ...";
  double uploadedPercent = 0.0;

  Future<void> upload() async {
    final response = await http.post(
      Uri.parse('https://jsonplaceholder.typicode.com/albums'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{
        'title': "test",
      }),
    );

    if (response.statusCode == 201) {
      // If the server did return a 201 CREATED response,
      // then parse the JSON.

      setState(() {
        status = "Uploaded";
        uploadedPercent = 1.0;
      });

      debugPrint(status);
    } else {
      throw Exception('Failed to create album.');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Upload File'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () {
                showDialog(
                  context: context,
                  builder: ((BuildContext context) {
                    return StatefulBuilder(builder: (context, setState) {
                      return AlertDialog(
                        title: Text(status),
                        content: LinearProgressIndicator(
                          value: uploadedPercent,
                          backgroundColor: Colors.grey,
                          color: Colors.green,
                          minHeight: 10,
                        ),
                      );
                    });
                  }),
                );
                upload();
              },
              child: const Text('Upload'),
            ),
          ],
        ),
      ),
      // buildFutureBuilder(),
    );
  }
}

my

status variable

and

uplaodPercent variable

not be update in alert dialog and the my LinearProgressBar() stay in this state :

my dialog

Huseyn
  • 372
  • 1
  • 7
  • 20

1 Answers1

2

I conducted an experiment, its essence was to put the setState (() {}); method inside the StatefulBuilder and periodically call it to redraw the AlertBox widget, everything worked out for me, here is an example:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: const Text("App bar"),
      ),
      body: HelpSO(count: 0.1),
    ));
  }
}

class HelpSO extends StatelessWidget {
  double count;

  HelpSO({Key? key, required this.count}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StatefulBuilder(builder:
        (BuildContext context, void Function(void Function()) setState) {
      Timer.periodic(const Duration(seconds: 2), (Timer t) {
        setState(() {
          count += 0.1;
          print(count);
        });
      });
      return AlertDialog(
        key: ValueKey(count),
        title: const Text("Loading..."),
        content: LinearProgressIndicator(
          value: count,
          backgroundColor: Colors.grey,
          color: Colors.green,
          minHeight: 10,
        ),
      );
    });
  }
}

enter image description here

So your problem is that everything works for you, but the widget is not redrawn, so try to put the setState(() {}); in StatefulBuilder and call it at the moment when your widget needs to be updated.

Legend5366
  • 451
  • 3
  • 12