【问题标题】:Issues with Flutter stateFlutter 状态的问题
【发布时间】:2020-01-21 11:05:35
【问题描述】:

这是一个 Flutter 实验。我试图在 Flutter 中创建一个段落生成器。做了一个用户界面

List<String> 加载数据。

data.dart

class MyData {
  static final List<String> data1 = [
    '0Title Of Page',
    '3Paragraph title One',
    '1First Paragraph Content Of Page',
    '3Paragraph title two',
    '1Second Paragraph Content Of Page',
    '4End of the page line',
  ];
}

我想将此列表中的第一项添加到AppBar() 的标题中,并且成功了。然后我想从这个列表中删除第一个项目(用作 AppBar 标题)并继续使用列表中的其余项目来构建 UI 的 body:

当我们第一次打开此页面时,它工作正常。从下一次开始,每次打开和关闭页面时,我们都会丢失列表中的第一项。即使页面是StatelessWidget,我们也会丢失项目并最终列出用完的项目。

我尝试过的事情:

  • 我尝试将页面和小部件更改为 StatelessWidget
  • 尝试overrideAppBar后退按钮和pop()页面。
  • 已将List&lt;String&gt; 复制到新变量。
  • 使用了dispose() 方法。

仍然会发生同样的情况。可能是什么问题?添加下面的代码。

main.dart

import 'package:flutter/material.dart';
import 'home_page.dart';
import 'page_one.dart';
import 'page_two.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Paragraph Test',
      initialRoute: '/',
      routes: {
        '/': (context) => HomePage(),
        '/pageone': (context) => PageOne(),
        '/pagetwo': (context) => PageTwo(),
      },
    );
  }
}

home_page.dart

import 'package:flutter/material.dart';
import 'button.dart';
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page Test'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          CButton(
            onTap: () {
              Navigator.pushNamed(context, '/pageone');
            },
            text: 'Page One',
          ),
          CButton(
            onTap: () {
              Navigator.pushNamed(context, '/pagetwo');
            },
            text: 'Page Two',
          ),
        ],
      ),
    );
  }
}

page_one.dart

import 'package:flutter/material.dart';
import 'data.dart';
var weight = FontWeight.normal;
var align = TextAlign.center;
var color = Colors.white60;
var size = 16.0;
String x, y;
class PageOne extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }
  @override
  Widget build(BuildContext context) {
    String title = MyData.data1.first.substring(1);
    MyData.data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: MyData.data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 1'),
        onPressed: () {},
      ),
    );
  }
}

page_two.dart

import 'package:flutter/material.dart';
import 'data.dart';
var weight = FontWeight.normal;
var align = TextAlign.center;
var color = Colors.white60;
var size = 16.0;
String x, y;
class PageTwo extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }
  @override
  Widget build(BuildContext context) {
    String title = MyData.data1.first.substring(1);
    MyData.data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: MyData.data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 2'),
        onPressed: () {},
      ),
    );
  }
}

button.dart

import 'package:flutter/material.dart';
class CButton extends StatelessWidget {
  CButton({this.text, this.onTap});
  final String text;
  final Function onTap;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        margin: EdgeInsets.all(2.0),
        padding: EdgeInsets.all(16.0),
        decoration: BoxDecoration(color: Colors.blue),
        child: Text(
          '$text',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

【问题讨论】:

  • 发生这种情况是因为您在 build 期间从列表中删除了项目。每次进入此屏幕时都会运行构建,因此您的列表为空。当在空列表上使用 list.first 时,屏幕截图中出现错误。
  • @Ryosuke 但是,页面的构建功能应​​该在关闭页面时失去其状态,对吧?所以当我们回到这个页面时,它应该正在重建并获得一个新的数据列表?为什么页面没有使用新的数据列表构建?

标签: flutter flutter-layout flutter-state statelesswidget


【解决方案1】:

data1static 类中的static 变量。所以它是一种具有命名空间MyData 的全局变量。所以每次你做MyData.data1.removeAt(0);都会影响同一个内存(或对象)。

根据你的情况试试这个,

class MyData {
  static List<String> get data1 => [
    '0Title Of Page',
    '3Paragraph title One',
    '1First Paragraph Content Of Page',
    '3Paragraph title two',
    '1Second Paragraph Content Of Page',
    '4End of the page line',
  ];
}
class PageOne extends StatelessWidget {
  buildText(String b) {
    x = b.substring(0, 1);
    y = b.substring(1);
    if (x.contains('0')) {
      weight = FontWeight.bold;
      color = Colors.blue;
      size = 18.0;
      align = TextAlign.center;
    } else if (x.contains('2')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.right;
      size = 16.0;
    } else if (x.contains('3')) {
      weight = FontWeight.normal;
      color = Colors.blue;
      align = TextAlign.center;
      size = 16.0;
    } else if (x.contains('4')) {
      weight = FontWeight.normal;
      color = Colors.red;
      align = TextAlign.center;
      size = 16.0;
    } else {
      weight = FontWeight.normal;
      color = Colors.white60;
      align = TextAlign.center;
      size = 16.0;
    }
    return y;
  }

  @override
  Widget build(BuildContext context) {
    final data1 = MyData.data1;
    String title = data1.first.substring(1);
    data1.removeAt(0);
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('$title'),
      ),
      body: Container(
        decoration: BoxDecoration(
          color: Colors.blueGrey,
        ),
        child: Container(
          width: double.infinity,
          height: double.infinity,
          margin: EdgeInsets.all(
            12.0,
          ),
          decoration: BoxDecoration(
            color: Color(0x99000000),
            borderRadius: BorderRadius.circular(10.0),
          ),
          child: SingleChildScrollView(
            padding: EdgeInsets.all(8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: data1
                  .map(
                    (item) => Text(
                      buildText(item),
                      textAlign: align,
                      style: TextStyle(
                        color: color,
                        fontWeight: weight,
                        fontSize: size,
                      ),
                    ),
                  )
                  .toList(),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Page 1'),
        onPressed: () {},
      ),
    );
  }
}

【讨论】:

  • 好的,成功了。这与小部件或应用程序的状态无关?
  • 是的。并且Stateless小部件中没有状态
  • get 的关键字是什么?
  • @AbyMathew 是定义 getter 函数的关键字。有了这个你可以只做var x = getter而不是var x = getter()
猜你喜欢
  • 2019-11-23
  • 2022-10-13
  • 1970-01-01
  • 2021-12-19
  • 2020-07-04
  • 2021-01-06
  • 2022-01-21
  • 2019-06-28
相关资源
最近更新 更多