首页 > 解决方案 > StatefullWidget 每次都重新初始化

问题描述

我试图简单地从 API 打印类别列表。我创建了我的 statefull 小部件,它工作正常。

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:playlife/models/Category.dart';
import 'package:playlife/globals.dart';


class CategoryMenu extends StatefulWidget {
  List<Category> list = List();

  CategoryMenu({Key key}) : super(key: key);

  @override
  _CategoryMenuState createState() => _CategoryMenuState();
}

class _CategoryMenuState extends State<CategoryMenu> {
  var isLoading = false;

  _fetchData() async {
    setState(() {
      isLoading = true;
    });
    final response =
        await http.get(baseApiUrl + '/v2/5ebc29a22e000054009f4261');
    if (response.statusCode == 200) {
      widget.list = (json.decode(response.body) as List)
          .map((data) => new Category.fromJson(data))
          .toList();
      setState(() {
        isLoading = false;
      });
    } else {
      throw Exception('Failed to load categories');
    }
  }

  @override
  void initState() {
    super.initState();
    if(widget.list.length == 0) {
    _fetchData();
    }
  }

  @override
  Widget build(BuildContext context) {
    return isLoading
      ? Center(
          child: CircularProgressIndicator(),
        )
      : ListView.builder(
          itemCount: widget.list.length,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              title: Text(widget.list[index].title, style: TextStyle(color: Colors.white)),
            );
          });

  }
}

在我的主页中,我只需将其添加到抽屉下

结束

rawer: Drawer( ....
            Row (
                  children: [
                    Expanded(
                      child: SizedBox(
                        height: 300.0,
                        child: CategoryMenu(),
                      )
                    ),
                  ],
                ),

再次,这工作正常。当我第一次打开菜单时,API 被称为 widget.list 被填充。下次我打开菜单时,不会调用 API,因为 widget.list 已经存在。现在我正在尝试将 Drawer 下的所有内容移动到无状态小部件中以重用它。

所以我只是创建了一个 StatelessWidget ,它与我在 endDrawer 之后的完全一样

class Menu extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Drawer(
        // Add a ListView to the drawer. This ensures the user can scroll
        // through the options in the drawer if there isn't enough vertical
        // space to fit everything.
        child: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.topRight,
              colors: [backgroundColor, backgroundColorTo])),
          child: ListView(
          // Important: Remove any padding from the ListView.
          padding: EdgeInsets.zero,
          children: <Widget>[
            Container(
                height: 80.0,
                child: DrawerHeader(
                    child: Text('', style: TextStyle(color: Colors.white)),
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topLeft,
                        end: Alignment.topRight,
                        colors: [backgroundColor, backgroundColorTo])),
                    margin: EdgeInsets.all(0.0),
                    padding: EdgeInsets.all(0.0)
              ),
            ),
            ListTile(
              title: Text('Discover', style: TextStyle(color: Colors.white)),
              onTap: () {
                // Update the state of the app
                // ...
                // Then close the drawer
                Navigator.pop(context);
              },
            ),
            ListTile(
              title: Text('Login', style: TextStyle(color: Colors.white)),
              onTap: () {
                // Update the state of the app
                // ...
                // Then close the drawer
                Navigator.pop(context);
              },
            ),
            Row (
              children: [
                Expanded(
                  child: SizedBox(
                    height: 300.0,
                    child: CategoryMenu(),
                  )
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

这就是问题开始的地方。每次我打开菜单都会调用 API。如果我在 initState 中打印 widget.list,我总是得到一个空列表。我还尝试使用 AsyncMemoizer,如下所述:https ://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2 并且还尝试对菜单使用 statefull 小部件。

我不明白为什么会这样。

标签: flutter

解决方案


您应该在主页的initState中调用_fetchData方法,如下所示:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<Category> list =[];
  var isLoading = false;

  _fetchData() async {
    //Do your Http call
  }

  @override
  void initState() {
    super.initState();
    _fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: YourBody(),
      drawer: Drawer(

      ),
    );
  }
}

推荐阅读