в Bloc не срабатывает CircularProgressIndicator при последующих задержках

У меня 2 вопроса. Вопрос 1

В функциях f1() f2() f3() происходит задержка

await Future.delayed(const Duration(seconds: 3));

имитирующая загрузку из интернета. При первом нажатии на любую кнопку, 2 секунды, как и положено, работает индикатор загрузки. А вот при следующих нажатиях на кнопки, он ПОЧЕМУ-ТО не работает. Ведь функция funWidget(Future future) каждый раз вызывается заново. Далее полный код и скриншот

main.dart

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';

enum EventWidget {widget1, widget2, widget3}

Future<int> f1() async {
 await Future.delayed(const Duration(seconds: 3));
 return 1;
}

Future<int> f2() async {
 await Future.delayed(const Duration(seconds: 3));
 return 2;
}

Future<int> f3() async {
 await Future.delayed(const Duration(seconds: 3));
 return 3;
}

Widget funWidget(Future<int> future) {
 return FutureBuilder(
  future: future,
  builder: (context, snapshot) {
   if (snapshot.hasData) {
    return Text(
     snapshot.data.toString(),
     style: const TextStyle(
      fontSize: 36.0,
      color: Colors.pink
     ),
    );
   } else if(snapshot.hasError) {
    return const Text(
     'Error',
     style: TextStyle(
      fontSize: 36.0,
      color: Colors.pink
     ),
    );
   } else {
    return const CircularProgressIndicator();
   }
  },
 );
}

//класс модель для бизнес-логики
//Bloc<события на вход, состояния на выход>
class ModelWidget extends Bloc<EventWidget, Widget> {

 late Widget widget;

 //тут нужно немного изменить
 ModelWidget(Widget widget) : super(widget) {

  //просто наберите on
  //(event, emit) это (EventWidget, Widget)
  on((event, emit) {
   switch(event) {
    case EventWidget.widget1:
     emit(
      widget = funWidget(f1())
     );
     break;
    case EventWidget.widget2:
     emit(
      widget = funWidget(f2())
     );
     break;
    case EventWidget.widget3:
     emit(
      widget = funWidget(f3())
     );
     break;
   }
  });

 }

}

void main() {
 runApp(
  MultiBlocProvider(
   providers: [

    BlocProvider<ModelWidget>(
     create: (BuildContext context) =>
      ModelWidget(
       const Text(
        '',
        style: TextStyle(
         fontSize: 36.0,
         color: Colors.pink
        ),
       )
      ), //инициализация
    ),

   ],
   child: const MyApp(),
  ),
 );
}

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

 @override
 Widget build(BuildContext context) {
  return MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'Name App',
   theme: ThemeData(
    primarySwatch: Colors.blue,
   ),
   home: const MyHomePage(),
  );
 }
}

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

 @override
 Widget build(BuildContext context) {

  final ModelWidget _modelWidget = BlocProvider.of<ModelWidget>(context);

  return Scaffold(
   appBar: AppBar(
    title: const Text('Name Page'),
   ),
   body: SafeArea(
    child: Column(
     //высота
     mainAxisSize: MainAxisSize.max,
     //выравнивание по оси Y, высота только mainAxisSize: MainAxisSize.max,
     mainAxisAlignment: MainAxisAlignment.start,
     //выравнивание по оси X, высота любая
     crossAxisAlignment: CrossAxisAlignment.center,
     children: [

      Padding(
       padding: const EdgeInsets.symmetric(vertical: 16.0),
       child: Row(
        //ширина
        mainAxisSize: MainAxisSize.max,
        //выравнивание по оси X, ширина только mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        //выравнивание по оси Y, ширина любая
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
         TextButton(
          onPressed: () { _modelWidget.add(EventWidget.widget1); },
          child: const Text('one'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
         TextButton(
          onPressed: () { _modelWidget.add(EventWidget.widget2); },
          child: const Text('two'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
         TextButton(
          onPressed: () { _modelWidget.add(EventWidget.widget3); },
          child: const Text('three'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
        ]
       ),
      ),

      Expanded(
       flex: 1,
       child: Align(
        alignment: Alignment.center,
        //виджет или дерево, которое будет изменяться, оборачиваем BlocBuilder
        //на вход класс модель, на выход класс состояния
        child: BlocBuilder<ModelWidget, Widget>(
         builder: (context, state) {
          return state;
         },
        ),
       ),
      ),

     ]
    ),
   ),
  );
 }

}

введите сюда описание изображения

Вопрос 2 В этом примере я использую в

BlocBuilder<ModelNumber, Future<int>>

виджет

FutureBuilder<int>

По всей видимости, ПОЧЕМУ-ТО в future: state, не передается state Может так вообще делать нельзя? Далее полный код и скриншот

main.dart

import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';

enum EventNumber {one, two, three}

Future<int> f1() async {
 await Future.delayed(const Duration(seconds: 3));
 return 1;
}

Future<int> f2() async {
 await Future.delayed(const Duration(seconds: 3));
 return 2;
}

Future<int> f3() async {
 await Future.delayed(const Duration(seconds: 3));
 return 3;
}

//класс модель для бизнес-логики
//Bloc<события на вход, состояния на выход>
class ModelNumber extends Bloc<EventNumber, Future<int>> {

 //тут нужно немного изменить
 ModelNumber() : super(Future.value(0)) {

  //просто наберите on
  //(event, emit) это (EventWidget, Widget)
  on((event, emit) {
   switch(event) {
    case EventNumber.one:
     emit(
      f1()
     );
     break;
    case EventNumber.two:
     emit(
      f2()
     );
     break;
    case EventNumber.three:
     emit(
      f3()
     );
     break;
   }
  });

 }

}

void main() {
 runApp(
  MultiBlocProvider(
   providers: [

    BlocProvider<ModelNumber>(
     create: (BuildContext context) =>
      ModelNumber(), //инициализация
    ),

   ],
   child: const MyApp(),
  ),
 );
}

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

 @override
 Widget build(BuildContext context) {
  return MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'Name App',
   theme: ThemeData(
    primarySwatch: Colors.blue,
   ),
   home: const MyHomePage(),
  );
 }
}

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

 @override
 Widget build(BuildContext context) {

  final ModelNumber _modelNumber = BlocProvider.of<ModelNumber>(context);

  return Scaffold(
   appBar: AppBar(
    title: const Text('Name Page'),
   ),
   body: SafeArea(
    child: Column(
     //высота
     mainAxisSize: MainAxisSize.max,
     //выравнивание по оси Y, высота только mainAxisSize: MainAxisSize.max,
     mainAxisAlignment: MainAxisAlignment.start,
     //выравнивание по оси X, высота любая
     crossAxisAlignment: CrossAxisAlignment.center,
     children: [

      Padding(
       padding: const EdgeInsets.symmetric(vertical: 16.0),
       child: Row(
        //ширина
        mainAxisSize: MainAxisSize.max,
        //выравнивание по оси X, ширина только mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        //выравнивание по оси Y, ширина любая
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
         TextButton(
          onPressed: () { _modelNumber.add(EventNumber.one); },
          child: const Text('one'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
         TextButton(
          onPressed: () { _modelNumber.add(EventNumber.two); },
          child: const Text('two'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
         TextButton(
          onPressed: () { _modelNumber.add(EventNumber.three); },
          child: const Text('three'),
          style: ButtonStyle(
           alignment: Alignment.center,
           minimumSize: MaterialStateProperty.all(const Size(88, 36)),
           foregroundColor: MaterialStateProperty.all(Colors.deepPurple),
           backgroundColor:  MaterialStateProperty.all(Colors.grey.shade200),
           padding: MaterialStateProperty.all(EdgeInsets.zero),
           textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 20)),
           shape: MaterialStateProperty.all(
            const RoundedRectangleBorder(
             borderRadius: BorderRadius.all(Radius.circular(5.0)),
            )
           ),
          ),
         ),
        ]
       ),
      ),

      Expanded(
       flex: 1,
       child: Align(
        alignment: Alignment.center,
        //виджет или дерево, которое будет изменяться, оборачиваем BlocBuilder
        //на вход класс модель, на выход класс состояния
        child: BlocBuilder<ModelNumber, Future<int>>(
         builder: (context, state) {
          return FutureBuilder<int>(
           future: state,
           builder: (context, snapshot) {
            if (snapshot.hasData) {
             return Text(
              snapshot.data.toString(),
              style: const TextStyle(
               fontSize: 36.0,
               color: Colors.pink
              ),
             );
            } else if(snapshot.hasError) {
             return const Text(
              'Error',
              style: TextStyle(
               fontSize: 36.0,
               color: Colors.pink
              ),
             );
            } else {
             return const CircularProgressIndicator();
            }
           },
          );
         },
        ),
       ),
      ),

     ]
    ),
   ),
  );
 }

}

введите сюда описание изображения


Ответы (0 шт):