我正在学习Flutter。我编写了一个小应用程序,用于从API获取密钥并将其打印在屏幕上。问题是我的getApiKey()
方法正在循环。
为什么?我该如何预防呢?
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider<TenderApiData>(
builder: (_) => TenderApiData(), child: HomePage()),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(), body: MyContainer());
}
}
class MyContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[MyTestWidget()],
);
}
}
class TenderApiData with ChangeNotifier {
String access_token;
String url = "https://";
getApiKey() async
{
var response = await http.post(url, headers: {"Accept": "application/json"});
// await Future.delayed(Duration(seconds: 25));
if (response.statusCode == 200)
{
access_token = json.decode(response.body)['access_token'];
notifyListeners();
}
}
}
class MyTestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
Provider.of<TenderApiData>(context).getApiKey();
var result = Provider.of<TenderApiData>(context).access_token;
return Row(
children: <Widget>[
Flexible(child: Text("Data: $result"))
],
);
}
}
答案 0 :(得分:4)
发生这种情况的原因是因为您是在getApiKey
函数中通知监听者,然后在getApiKey
方法中是调用 build
。通知侦听器时调用build
方法,看看为什么循环?
无论如何,要防止发生这种情况,您只需将StatelessWidget
转换为StatefulWidget
并仅在State.didChangeDependencies
中调用getApiKey
(而不是initState
中,因为您需要访问BuildContext
):
class MyTestWidget extends StatefulWidget {
@override
_MyTestWidgetState createState() => _MyTestWidgetState();
}
class _MyTestWidgetState extends State<MyTestWidget> {
bool apiKeyLoaded;
@override
void initState() {
apiKeyLoaded = false;
super.initState();
}
@override
void didChangeDependencies() {
if (!apiKeyLoaded) {
Provider.of<TenderApiData>(context).getApiKey();
apiKeyLoaded = true;
}
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
var result = Provider
.of<TenderApiData>(context)
.access_token;
return Row(
children: <Widget>[
Flexible(child: Text("Data: $result"))
],
);
}
}