第八十二回:Widget的生命周期

文章介绍了Flutter中StatefulWidget的生命周期,包括initState()用于初始化,build()用于构建Widget,以及dispose()用于释放资源。通过示例代码展示了这三个关键生命周期方法的使用,并提示读者可以结合Android或iOS的生命周期知识进行对比理解。


我们在上一章回中介绍了Flutter中如何使用三方包相关的内容,本章回中将介绍 Widget的生命周期.闲话休提,让我们一起Talk Flutter吧。

概念介绍

本章回中介绍的生命周期是指Widget从创建到结果的整个过程,这里提到的Widget是一个泛称,更加准确的说是StatefulWidget,因为StatelessWidget没有具体的State

在程序开发过程中需要明白Widget的生命周期,这样才能生命周期中不同的阶段做不同的事情,常见是在创建Widget时初始化某些数据,在销毁Widget时释放相关的资源。

使用方法

生命周期是一个抽象的概念,不容易操作,不过不用担心,Flutter在生命周期中不同的阶段提供了不同的回调方法,我们称其为生命周期回调方法。我们只需要使用生命周期回调方法就可以去完全生命中相关的操作。接下来我们介绍相关的生命周期方法:

  • initState()方法:主要用来初始化Widget相关的内容;
  • build()方法:主要用来创建Widget,它不可以创建子Widget;
  • dispose()方法:主要用来释放Widget相关的资源;

我们在这里只介绍了三个重要的生命周期方法,其它的生命周期方法先不介绍,后续遇到后再做详细介绍。如果看官们有Android或者IOS的开发经验,那么可以使用这两个平台中生命周期的概念来对比,以及这两个平台中相关的的生命周期回调方法来做对比,比如onCreate,onResume,willApper,DidLoad等生命周期方法。

示例代码


class ExLoadingPage extends StatefulWidget {
  const ExLoadingPage({Key? key}) : super(key: key);

  
  State<ExLoadingPage> createState() => _ExLoadingPageState();
}

class _ExLoadingPageState extends State<ExLoadingPage> {
  
  void initState() {
    // TODO: implement initState
    super.initState();
    print("Widget Circle: initState");
  }

  
  Widget build(BuildContext context) {
    print("Widget Circle: build");

    return Container(
      child: Image.asset("images/ex.png"),
    );
  }

  
  void dispose() {
    print("Widget Circle: dispose");
    super.dispose();
  }
}

编译并且运行上面的程序可以得到以下运行结果。注意:在运行过程中需要使用路由来切换页面,不然无法走到dispose这个生命周期方法中:

I/flutter ( 9836): Widget Circle: initState
I/flutter ( 9836): Widget Circle: build
I/flutter ( 9836): Widget Circle: dispose

看官们,关于"Widget生命周期"相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!

#include "widget.h" #include <QDebug> #include <QMessageBox> #include <QFont> #include <QMediaPlaylist> Widget::Widget(QWidget *parent) : QWidget(parent), stackedWidget(nullptr), mainPage(nullptr), loginRegisterPage(nullptr), pageLogin(nullptr), pageRegister(nullptr), titleLabel(nullptr), btnRegisterLogin(nullptr), btnStartGame(nullptr), btnSettings(nullptr), btnLeaderboard(nullptr), btnExit(nullptr), gifLabel(nullptr), movie(nullptr), settingmusicPage(nullptr), dbManager(nullptr), roleSelectionPage(nullptr), levelSelectionPage(nullptr), selectedRoleIndex(-1) { setWindowTitle("哈基迷大探险"); resize(800, 700); move(550, 50); setWindowIcon(QIcon(":/picture/mimi1.png")); stackedWidget = new QStackedWidget(this); QVBoxLayout *mainContainerLayout = new QVBoxLayout(this); mainContainerLayout->addWidget(stackedWidget); mainContainerLayout->setContentsMargins(0, 0, 0, 0); setLayout(mainContainerLayout); mainPage = new QWidget(); QVBoxLayout *mainPageLayout = new QVBoxLayout(mainPage); titleLabel = new QLabel(mainPage); titleLabel->setAlignment(Qt::AlignCenter); titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); titleLabel->setMinimumSize(800, 200); QPixmap originalPixmap(":/picture/title.png"); if (!originalPixmap.isNull()) { QPixmap scaledPixmap = originalPixmap.scaled( titleLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ); titleLabel->setPixmap(scaledPixmap); } else { titleLabel->setText("图片加载失败"); titleLabel->setStyleSheet("color: red"); } mainPageLayout->addWidget(titleLabel); mainPageLayout->addSpacing(40); QGridLayout *gridLayout = new QGridLayout(); btnRegisterLogin = new QPushButton("注册/登录", mainPage); btnStartGame = new QPushButton("开始游戏", mainPage); btnSettings = new QPushButton("游戏设置", mainPage); btnLeaderboard = new QPushButton("排行榜", mainPage); btnExit = new QPushButton("退出游戏", mainPage); QFont btnFont("Arial", 14); QPushButton* btns[] = {btnRegisterLogin, btnStartGame, btnSettings, btnLeaderboard, btnExit}; for (auto btn : btns) { btn->setFont(btnFont); btn->setMinimumSize(200, 50); btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); btn->setStyleSheet( "QPushButton {" " background-color: pink;" " color: white;" " border: 2px solid white;" " font: bold 14px;" " border-radius: 10px;" "}" "QPushButton:hover {" " background-color: #ff88aa;" "}" "QPushButton:pressed {" " background-color: white;" " color: pink;" "}" ); } gridLayout->addWidget(btnRegisterLogin, 0, 0); gridLayout->addWidget(btnStartGame, 0, 1); gridLayout->addWidget(btnSettings, 1, 0); gridLayout->addWidget(btnLeaderboard, 1, 1); gridLayout->addWidget(btnExit, 2, 0, 1, 2); gridLayout->setSpacing(20); gridLayout->setContentsMargins(50, 20, 50, 20); mainPageLayout->addLayout(gridLayout); gifLabel = new QLabel(mainPage); gifLabel->setAlignment(Qt::AlignCenter); movie = new QMovie(":/gif/mimi2.gif", QByteArray(), mainPage); if (movie->isValid()) { gifLabel->setMovie(movie); movie->start(); gifLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } else { gifLabel->setText("动图加载失败"); gifLabel->setStyleSheet("color: red"); } mainPageLayout->addWidget(gifLabel); mainPageLayout->setContentsMargins(10, 10, 10, 10); mainPageLayout->setSpacing(10); mainPage->setLayout(mainPageLayout); loginRegisterPage = new childwidget(); pageLogin = new Login(); pageRegister = new RegisterWidget(); stackedWidget->addWidget(mainPage); stackedWidget->addWidget(loginRegisterPage); stackedWidget->addWidget(pageLogin); stackedWidget->addWidget(pageRegister); dbManager = new DatabaseManager(this); if (!dbManager->initDatabase()) { QMessageBox::critical(this, "数据库错误", "无法初始化数据库,请检查应用权限"); } roleSelectionPage = new RoleSelection(); stackedWidget->addWidget(roleSelectionPage); levelSelectionPage = new LevelSelection(); stackedWidget->addWidget(levelSelectionPage); rankingListPage = new RankingList(); stackedWidget->addWidget(rankingListPage); settingmusicPage = new settingmusic(this); stackedWidget->addWidget(settingmusicPage); connect(settingmusicPage, &settingmusic::backToPrevious, this, [=]() { stackedWidget->setCurrentWidget(mainPage); }); connect(btnSettings, &QPushButton::clicked, this, [=]() { stackedWidget->setCurrentWidget(settingmusicPage); }); connect(btnLeaderboard, &QPushButton::clicked, this, [=]() { QVector<RankingInfo> rankingData = dbManager->getRankingList(-1); rankingListPage->setRankingData(rankingData); stackedWidget->setCurrentWidget(rankingListPage); qDebug() << "切换到排行榜页面"; }); connect(rankingListPage, &RankingList::backToMainPage, this, [=]() { stackedWidget->setCurrentWidget(mainPage); }); connect(btnRegisterLogin, &QPushButton::clicked, this, &Widget::onRegisterLoginClicked); connect(loginRegisterPage, &childwidget::backToMainPage, this, &Widget::onBackToMainPage); connect(loginRegisterPage, &childwidget::gotoLoginPage, this, &Widget::onGotoLogin); connect(loginRegisterPage, &childwidget::gotoRegisterPage, this, &Widget::onGotoRegister); connect(pageLogin, &Login::loginRequested, this, &Widget::handleLogin); connect(pageRegister, &RegisterWidget::registerRequested, this, &Widget::handleRegister); connect(pageLogin, &Login::backToPrevious, this, &Widget::onRegisterLoginClicked); connect(pageRegister, &RegisterWidget::backToPrevious, this, &Widget::onRegisterLoginClicked); connect(btnExit, &QPushButton::clicked, this, &Widget::close); connect(btnSettings, &QPushButton::clicked, this, [=]() { stackedWidget->setCurrentWidget(settingmusicPage); }); connect(this, &Widget::loginSuccess, this, [=]() { stackedWidget->setCurrentWidget(roleSelectionPage); qDebug() << "登录成功,跳转至角色选择页"; }); connect(roleSelectionPage, &RoleSelection::backToPrevious, this, [=]() { stackedWidget->setCurrentWidget(mainPage); }); connect(roleSelectionPage, &RoleSelection::roleConfirmed, this, [=](int index) { QMessageBox::information(this, "选择成功", QString("你选择了角色:%1").arg(roleSelectionPage->getRoleInfo(index).name)); selectedRoleIndex = index; stackedWidget->setCurrentWidget(levelSelectionPage); }); connect(levelSelectionPage, &LevelSelection::backToRoleSelection, this, [=]() { stackedWidget->setCurrentWidget(roleSelectionPage); }); connect(levelSelectionPage, &LevelSelection::levelConfirmed, this, &Widget::handleLevelSelected); connect(btnStartGame, &QPushButton::clicked, this, [=]() { if (currentUsername.isEmpty()) { QMessageBox::information(this, "提示", "请先登录才能开始游戏!"); stackedWidget->setCurrentWidget(pageLogin); } else { stackedWidget->setCurrentWidget(roleSelectionPage); } }); } Widget::~Widget() { delete movie; } void Widget::onRegisterLoginClicked() { stackedWidget->setCurrentWidget(loginRegisterPage); qDebug() << "切换到登录/注册选择页面"; } void Widget::onBackToMainPage() { stackedWidget->setCurrentWidget(mainPage); qDebug() << "切回主页面"; } void Widget::onGotoLogin() { stackedWidget->setCurrentWidget(pageLogin); qDebug() << "切换到登录页面"; } void Widget::onGotoRegister() { stackedWidget->setCurrentWidget(pageRegister); qDebug() << "切换到注册页面"; } void Widget::handleLogin(const QString& username, const QString& password) { if (dbManager->verifyUser(username, password)) { QMessageBox::information(this, "登录成功", "欢迎回来," + username + "!"); currentUsername = username; emit loginSuccess(); } else { QMessageBox::warning(this, "登录失败", "用户名或密码错误"); } } void Widget::handleRegister(const QString &username, const QString &password, const QString &confirmPassword) { if (password != confirmPassword) { QMessageBox::warning(this, "注册失败", "两次输入的密码不一致!"); return; } if (!dbManager->m_db.isOpen() && !dbManager->m_db.open()) { QMessageBox::critical(this, "注册失败", "数据库连接失败,请重试!"); return; } if (dbManager->registerUser(username, password)) { QMessageBox::information(this, "注册成功", "注册成功,请登录!"); stackedWidget->setCurrentWidget(pageLogin); } else { QMessageBox::warning(this, "注册失败", "用户名已存在或注册失败!"); } } void Widget::handleRoleSelected(int index) { selectedRoleIndex = index; qDebug() << "选择角色索引:" << index; stackedWidget->setCurrentWidget(levelSelectionPage); } void Widget::handleLevelSelected(int levelIndex) { if (selectedRoleIndex == -1) { QMessageBox::warning(this, "错误", "请先选择角色!"); return; } Player::RoleType roleType = (selectedRoleIndex == 0) ? Player::RoleType::Mimi : Player::RoleType::Yika; GameWidget* gameWidget = new GameWidget(roleType, levelIndex, currentUsername, dbManager, this); gameWidget->show(); } 具体解释一下每行代码什么意思
09-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值