Flutter - 在独立 class 中调用异步函数
Flutter - Calling an async function within an independent class
我在 main.dart 中声明了一个函数,它可以帮助我获得 deviceId
。
我正在尝试将其设置为独立 class 的变量,其构造函数稍后在我的一个小部件中创建。
函数:
Future<String?> _getId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isIOS) { // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
return iosDeviceInfo.identifierForVendor; // Unique ID on iOS
} else {
var androidDeviceInfo = await deviceInfo.androidInfo;
return androidDeviceInfo.androidId; // Unique ID on Android
}
}
在 class 中将其称为:
class _Data {
String? fullname = '';
String doctor = 's';
String? deviceId = await _getId();
}
我遇到以下错误:
The await expression can only be used in an async function.
完整代码:
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:device_info_plus/device_info_plus.dart';
Future<String?> _getId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isIOS) { // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
return iosDeviceInfo.identifierForVendor; // Unique ID on iOS
} else {
var androidDeviceInfo = await deviceInfo.androidInfo;
return androidDeviceInfo.androidId; // Unique ID on Android
}
}
void main() => runApp(const MaterialApp(
title: 'Manager',
home: RegisterPage(),
));
class RegisterPage extends StatefulWidget {
const RegisterPage ({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _RegisterPageState();
}
class _Data {
String? fullname = '';
String doctor = 's';
String? deviceId = await _getId();
}
class _RegisterPageState extends State<RegisterPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
_Data _data = _Data();
void submit() {
_formKey.currentState!.save();
print('Printing the login data.');
print('Fullname: ${_data.fullname}');
print('Doctor: ${_data.doctor}');
print('Device Id: ${_data.getDeviceId()}');
}
@override
Widget build(BuildContext context) {
final Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('Manager'),
),
body: Container(
padding: const EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
hintText: 'John Doe',
labelText: 'Full name'
),
onSaved: (String? value) {
_data.fullname = value;
}
),
Container(
width: screenSize.width,
margin: const EdgeInsets.only(
top: 20.0
),
child: ElevatedButton(
onPressed: submit,
child: const Text(
'Register',
style: TextStyle(
color: Colors.white
),
),
),
)
],
),
)
),
);
}
}
点击提交时显示正确的全名值,但调用设备 ID 时出错
await 关键字只能与 async 函数一起使用。
仅使用函数,但在这里您在 class 中调用了 await _getId()
而不是在函数中。
试试这个。
@override
void initState() {
// TODO: implement initState
super.initState();
_getId().then((value) {
_data.deviceId = value;
});
//print(_data.deviceId);
}
您想从异步操作的结果中初始化 deviceId
。部分选项:
声明Future<String?> deviceId = _getId();
并要求所有调用者在访问它时await
它。
稍后初始化:
class _Data {
String? deviceId;
_Data() {
_getId().then((id) => deviceId = id);
}
}
请注意,使用这种方法,调用者将不会在 deviceId
最终初始化时收到通知。
让调用者异步初始化您的 class:
class _Data {
String? deviceId;
_Data._(this.deviceId);
static Future<_Data> newData() async {
var id = await _getId();
return _Data._(id);
}
}
有些相关:
您正在做的很多事情都会被认为是不好的做法。我将进行一些更改,最后回答您的问题。定义你的 _Data class 如下:
class _Data {
String? fullname;
String doctor;
String? deviceId;
_Data(this.fullname, this.doctor, this.deviceId);
}
这样您的数据模型就不会被硬编码。您也可以考虑将这些字段设置为最终字段,除非您有充分的理由不这样做。
声明数据状态变量:
_Data? _data;
在您的状态中定义 initData 方法:
Future<void> initData() async {
var dat = _Data("fn", "doc", await _getId());
setState(() {_data = dat; });
}
最终覆盖 initState:
@override
void initState() {
super.initState();
initData();
}
在您的构建方法中,您可以注意该字段是否为空(检查它是否已被初始化)。一旦你得到它,这里有很多改进的空间 运行。首先,您不应该将 getId 方法设为顶级,最好将其放在服务中,并且您应该考虑使用未来的构建器,而不是让 _data 状态属性可为空。
我在 main.dart 中声明了一个函数,它可以帮助我获得 deviceId
。
我正在尝试将其设置为独立 class 的变量,其构造函数稍后在我的一个小部件中创建。
函数:
Future<String?> _getId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isIOS) { // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
return iosDeviceInfo.identifierForVendor; // Unique ID on iOS
} else {
var androidDeviceInfo = await deviceInfo.androidInfo;
return androidDeviceInfo.androidId; // Unique ID on Android
}
}
在 class 中将其称为:
class _Data {
String? fullname = '';
String doctor = 's';
String? deviceId = await _getId();
}
我遇到以下错误:
The await expression can only be used in an async function.
完整代码:
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:device_info_plus/device_info_plus.dart';
Future<String?> _getId() async {
var deviceInfo = DeviceInfoPlugin();
if (Platform.isIOS) { // import 'dart:io'
var iosDeviceInfo = await deviceInfo.iosInfo;
return iosDeviceInfo.identifierForVendor; // Unique ID on iOS
} else {
var androidDeviceInfo = await deviceInfo.androidInfo;
return androidDeviceInfo.androidId; // Unique ID on Android
}
}
void main() => runApp(const MaterialApp(
title: 'Manager',
home: RegisterPage(),
));
class RegisterPage extends StatefulWidget {
const RegisterPage ({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _RegisterPageState();
}
class _Data {
String? fullname = '';
String doctor = 's';
String? deviceId = await _getId();
}
class _RegisterPageState extends State<RegisterPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
_Data _data = _Data();
void submit() {
_formKey.currentState!.save();
print('Printing the login data.');
print('Fullname: ${_data.fullname}');
print('Doctor: ${_data.doctor}');
print('Device Id: ${_data.getDeviceId()}');
}
@override
Widget build(BuildContext context) {
final Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('Manager'),
),
body: Container(
padding: const EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.text,
decoration: const InputDecoration(
hintText: 'John Doe',
labelText: 'Full name'
),
onSaved: (String? value) {
_data.fullname = value;
}
),
Container(
width: screenSize.width,
margin: const EdgeInsets.only(
top: 20.0
),
child: ElevatedButton(
onPressed: submit,
child: const Text(
'Register',
style: TextStyle(
color: Colors.white
),
),
),
)
],
),
)
),
);
}
}
点击提交时显示正确的全名值,但调用设备 ID 时出错
await 关键字只能与 async 函数一起使用。
仅使用函数,但在这里您在 class 中调用了 await _getId()
而不是在函数中。
试试这个。
@override
void initState() {
// TODO: implement initState
super.initState();
_getId().then((value) {
_data.deviceId = value;
});
//print(_data.deviceId);
}
您想从异步操作的结果中初始化 deviceId
。部分选项:
声明
Future<String?> deviceId = _getId();
并要求所有调用者在访问它时await
它。稍后初始化:
class _Data { String? deviceId; _Data() { _getId().then((id) => deviceId = id); } }
请注意,使用这种方法,调用者将不会在
deviceId
最终初始化时收到通知。让调用者异步初始化您的 class:
class _Data { String? deviceId; _Data._(this.deviceId); static Future<_Data> newData() async { var id = await _getId(); return _Data._(id); } }
有些相关:
您正在做的很多事情都会被认为是不好的做法。我将进行一些更改,最后回答您的问题。定义你的 _Data class 如下:
class _Data {
String? fullname;
String doctor;
String? deviceId;
_Data(this.fullname, this.doctor, this.deviceId);
}
这样您的数据模型就不会被硬编码。您也可以考虑将这些字段设置为最终字段,除非您有充分的理由不这样做。
声明数据状态变量:
_Data? _data;
在您的状态中定义 initData 方法:
Future<void> initData() async {
var dat = _Data("fn", "doc", await _getId());
setState(() {_data = dat; });
}
最终覆盖 initState:
@override
void initState() {
super.initState();
initData();
}
在您的构建方法中,您可以注意该字段是否为空(检查它是否已被初始化)。一旦你得到它,这里有很多改进的空间 运行。首先,您不应该将 getId 方法设为顶级,最好将其放在服务中,并且您应该考虑使用未来的构建器,而不是让 _data 状态属性可为空。