如何防止我的构建方法循环?

Dmi*_*kov 1 dart 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"))
      ],

    );
  }
}
Run Code Online (Sandbox Code Playgroud)

cre*_*not 6

发生这种情况的原因是您在getApiKey函数中通知侦听器,然后在方法中调用 。当您通知您的听众时会调用该方法,看看为什么会循环?getApiKeybuildbuild

不管怎么说,以防止它,您只需将您StatelessWidgetStatefulWidget只有调用getApiKeyState.didChangeDependencies(不是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"))
      ],

    );
  }
}
Run Code Online (Sandbox Code Playgroud)