Solución:
Te sugiero que uses un FutureBuilder
:
import 'package:flutter/material.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// save in the state for caching!
DeviceInfoPlugin _deviceInfoPlugin;
@override
void initState() {
super.initState();
_deviceInfoPlugin = DeviceInfoPlugin();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Device Info',
home: Scaffold(
appBar: AppBar(
title: Text('My Device Info'),
),
body: FutureBuilder<AndroidDeviceInfo>(
future: _deviceInfoPlugin.androidInfo,
builder: (BuildContext context, AsyncSnapshot<AndroidDeviceInfo> snapshot) {
if (!snapshot.hasData) {
// while data is loading:
return Center(
child: CircularProgressIndicator(),
);
} else {
// data loaded:
final androidDeviceInfo = snapshot.data;
return Center(
child: Text('Android version: ${androidDeviceInfo.version}'),
);
}
},
),
),
);
}
}
En general, al usar FutureBuilder
o Future
s, debe tener en cuenta que el widget adjunto se puede reconstruir en cualquier momento (por ejemplo, porque se giró el dispositivo o se muestra el teclado). Eso significa el build
se llama de nuevo al método.
En este caso particular, no es un problema porque el complemento almacena en caché el valor y lo devuelve instantáneamente, pero en general NUNCA debe crear u obtener un Future
dentro de la build
método. En cambio, hazlo desde initState
o un controlador de eventos de clic:
import 'package:flutter/material.dart';
class FooWidget extends StatefulWidget {
@override
_FooWidgetState createState() => _FooWidgetState();
}
class _FooWidgetState extends State<FooWidget> {
Future<int> _bar;
@override
void initState() {
super.initState();
_bar = doSomeLongRunningCalculation();
}
void _retry() {
setState(() {
_bar = doSomeLongRunningCalculation();
});
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
FutureBuilder<int>(
future: _bar,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasData) {
return Text('The answer to everything is ${snapshot.data}');
} else {
return Text('Calculating answer...');
}
},
),
RaisedButton(
onPressed: _retry,
child: Text('Retry'),
)
],
);
}
}
Future<int> doSomeLongRunningCalculation() async {
await Future.delayed(Duration(seconds: 5)); // wait 5 sec
return 42;
}
build()
espera un resultado de sincronización, así que usando async
/await
es inapropiado en build()
.
Utilice FutureBuilder donde devuelve un marcador de posición Container()
mientras que el resultado asincrónico aún no está disponible o mueva el código asincrónico a initState()
y actualice el estado usando setState
cuando el valor esté disponible para tener el build
ser ejecutado de nuevo.
Puede lograrlo mediante el uso de esperar / asincrónico (Por @ Günter Zöchbauer dijo que no es necesario importar lib según la última versión de dart).
y llamar a funciones fuera del método de construcción.
_getAndroidDeviceInfo() async{
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
print(androidInfo.device);
}
_get_iOS_DeviceInfo() async{
IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
print(iosDeviceInfo.model);
}