在Build方法外部创建的Future Builder内部创建的颤动使用变量, [英] Flutter use variable created inside Future builder outside of the build method,
本文介绍了在Build方法外部创建的Future Builder内部创建的颤动使用变量,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个将来的构建器,我使用它来获取数据,我需要将从API获得的使用到一个必须在build外部定义的文本编辑控制器,并且我需要给文本编辑控制器一个初始值,在这个初始值中,我需要放入data3.firstName和data3.lastName,因为现在初始值是硬编码的。
Future<Response> fetchAccountData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? authorization = prefs.getString('authorization');
var url = 'https://dev.api.wurk.skyver.co/api/v1/employees/account';
response1 = await http.get(
Uri.parse(url),
headers: <String, String>{
'authorization': authorization ?? basicAuth.toString()
},
);
return response1;
}
factory AccountData.fromJson(Map<String, dynamic> json) {
return AccountData(
firstName: json['firstName'],
lastName: json['lastName'],
phoneNumber: json['phoneNumber']);
}
}
Future<void> putAccountData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? authorization = prefs.getString('authorization');
var url = 'https://dev.api.wurk.skyver.co/api/v1/employees/account';
Map payload = {
"firstName": editedFirstName.text,
"lastName": editedLastName.text,
};
try {
final response = await http.put(Uri.parse(url),
headers: <String, String>{
'authorization': authorization ?? basicAuth.toString(),
"Content-Type": "application/json"
},
body: jsonEncode(payload));
} catch (er) {}
}
TextEditingController editedFirstName =
TextEditingController(text: 'firstName'); << needs to be data3.firstName
TextEditingController editedLastName =
TextEditingController(text: 'lastName');<< needs to be data3.lastName
return SafeArea(
child: WillPopScope(
onWillPop: () async {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const ProfileScreen(),
),
);
return shouldPop;
},
body: FutureBuilder<Response>(
future: futureData,
builder: (context, snapshot) {
if (snapshot.hasData) {
AccountData data3 = AccountData.fromJson( << data3 has data3.firstName, and
data3.lastName
json.decode(snapshot.data!.body),
);
推荐答案
我不完全理解拥有全局文本控制器的原因(我也不认为这是一个好主意),但使用Riverpod时,它看起来会是这样的:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class AccountData {
final String firstName;
final String lastName;
final String phoneNumber;
AccountData({
required this.firstName,
required this.lastName,
required this.phoneNumber,
});
factory AccountData.fromJson(Map<String, dynamic> json) {
return AccountData(
firstName: json['firstName'],
lastName: json['lastName'],
phoneNumber: json['phoneNumber'],
);
}
}
Future<Map<String, dynamic>> fetchAccountData() async {
final response = {
'firstName': 'Name',
'lastName': 'LastName',
'phoneNumber': '98786758690',
};
return Future.delayed(const Duration(seconds: 3), () => response);
}
final futureData = FutureProvider<AccountData>((_) async {
final data = await fetchAccountData();
return AccountData.fromJson(data);
});
final firstNameController = ChangeNotifierProvider<TextEditingController>((ref) {
final controller = TextEditingController();
ref.listen<AsyncValue<AccountData>>(futureData, (_, curr) {
curr.whenOrNull(
data: (d) => controller.text = d.firstName,
);
});
return controller;
});
final lastNameController = ChangeNotifierProvider<TextEditingController>((ref) {
final controller = TextEditingController();
ref.listen<AsyncValue<AccountData>>(futureData, (_, curr) {
curr.whenOrNull(
data: (d) => controller.text = d.lastName,
);
});
return controller;
});
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final firstController = ref.watch(firstNameController.notifier);
final lastcontroller = ref.watch(lastNameController.notifier);
return ref.watch(futureData).when(
loading: () => const CircularProgressIndicator(),
error: (e, _) => TextButton(
child: Text('$e'),
onPressed: () => ref.refresh(futureData),
),
data: (_) {
return Column(
children: [
TextField(
controller: firstController,
),
TextField(
controller: lastcontroller,
),
]
);
}
);
}
}
现在,在Hazar Belge之后使用后期初始值设定项是一个好主意,如果没有状态管理,这个想法将是简单地使用FutureBuilder,然后将数据向下传递给StatefulWidget,后者使用该数据初始化TextEditingController,然后再次使用didUpdateWidget,所有这些都不依赖于外部包(您的应用程序越大,您将需要使用更多的包来帮助您快速开发,但我建议您尝试使用Basic来掌握您所能做的所有事情),所有这些都不依赖于外部包(您的应用程序越大,您就需要使用更多的包来帮助您快速开发,但我建议您尝试使用Basic来掌握您能做的所有事情
这篇关于在Build方法外部创建的Future Builder内部创建的颤动使用变量,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文