Flutter: показ прелоадера при загрузке данных в виджете showDialog
Задача: при отображении данных при помощи виджета showDialog, необходимо показывать «прелоадер» во время загрузки данных со стороннего ресурса.

Решение: для отображения прелоадера, используем пакет card_loader. Однако! дело осложняется тем, что виджет showDialog не имеет метода setState, соответственно у нас нет возможности изменить уже отображенные данные, после окончания загрузки.
Для обхода этого ограничения, оформим showDialog как полноценный StatefulWidget с получением в связи с этим стандартных плюшек в виде setState, а так-же возможность вызова своих процедур после окончания отображения виджета:
import 'package:flutter/material.dart';
import 'package:card_loading/card_loading.dart';
import 'dart:convert';
class MyMeDialogInfo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyMeDialogInfoState();
}
}
class _MyMeDialogInfoState extends State<MyMeDialogInfo> {
bool info_is_load=false;
void RefreshMeDialogData(context){
TRequests req=new TRequests();
req.request("adfserfserf", {}), (List result){
setState(() {
//info_is_load=true;
});
}, (String error){
});
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => RefreshMeDialogData(context)); // эвент после того как страница отобразилась - обновим данные по пользователю
}
@override
Widget build(BuildContext context) {
return Align (
alignment: Alignment.bottomCenter,
child:
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32.0),
topRight: Radius.circular(32.0))),
child:Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// заголовок окна
Padding(
padding: const EdgeInsets.all(16.0),
child: Material(
child: Text("Заголовок окна", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0, color: Colors.black))),
),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 220,
decoration: BoxDecoration(),
child:
SingleChildScrollView(
child: Stack(
children: <Widget>[
Visibility(
visible: info_is_load,
child:
Padding(
padding: const EdgeInsets.all(16.0),
child: Material(
child: Text("Тут перечисляем какую инфу загружаемую асинхронно", style: TextStyle(fontSize: 14.0, color: Colors.black))),
)
),
Visibility(
visible: !info_is_load,
child:
Padding(
padding: const EdgeInsets.only(bottom: 20,left: 20,right: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
CardLoading(
height: 30,
borderRadius: BorderRadius.all(Radius.circular(15)),
width: 100,
margin: EdgeInsets.only(bottom: 10),
),
CardLoading(
height: 100,
borderRadius: BorderRadius.all(Radius.circular(15)),
margin: EdgeInsets.only(bottom: 10),
),
CardLoading(
height: 30,
width: 200,
borderRadius: BorderRadius.all(Radius.circular(15)),
margin: EdgeInsets.only(bottom: 10),
),
],
),
)
)
],
),
),
)
]
)
)
);
}
}
class TMeDialog {
void MeDialogInfoDialog(BuildContext context,Map ezs){
showDialog(
context: context,
builder: (BuildContext context) {
return MyMeDialogInfo(ezs);
},
);
}
}