为什么我必须执行热重启才能在 Flutter 中查看我的数据库中的更改?
Why do I have to perform a hot restart to see the changes in my database in Flutter?
我正在学习 Flutter,我正在尝试使用 SQFLite 包在设备上保存数据。一切正常,但有一个问题,每次我添加一个新元素或升级它时,我都需要重新启动我的应用程序才能看到更改,我不知道为什么,没有错误或任何东西。
我把它上传到 github 所以你可以试试,也许是我的模拟器里的东西或者我不知道的东西。
https://github.com/Rodrigogzmn6/sql_demo
或者您可以在此处查看完整项目的一部分
主页
import 'package:flutter/material.dart';
import 'package:sql_demo/models/product.dart';
import 'package:sql_demo/pages/add_product_page.dart';
import 'package:sql_demo/pages/update_product_page.dart';
import 'package:sql_demo/pages/view_product_page.dart';
import 'package:sql_demo/services/dbhelper.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DbHelper helper;
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: FutureBuilder(
future: helper.getProducts(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Product product = Product.fromMap(snapshot.data[index]);
return ListTile(
contentPadding: const EdgeInsets.all(16.0),
title: Text(
'${product.name} - $${(product.price).toString()}'),
subtitle: Text(product.description),
trailing: Column(
children: [
Expanded(
child: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
setState(() {
helper.deleteProduct(product.id);
});
}),
),
SizedBox(
height: 20.0,
),
Expanded(
child: IconButton(
icon: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateProductPage(
product: product,
)),
);
}),
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsPage(
product: product,
)));
},
);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
}),
);
}
}
正在创建项目页面
import 'package:flutter/material.dart';
import 'package:sql_demo/models/product.dart';
import 'package:sql_demo/services/dbhelper.dart';
class AddProductPage extends StatefulWidget {
@override
_AddProductPageState createState() => _AddProductPageState();
}
class _AddProductPageState extends State<AddProductPage> {
String name, description;
num price;
DbHelper helper;
//Instantiate Helper
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add new product"),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product name',
labelText: 'Product name',
),
onChanged: (value) {
setState(() {
name = value;
});
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product description',
labelText: 'Product description',
),
onChanged: (value) {
setState(() {
description = value;
});
},
),
SizedBox(height: 16),
TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Enter product price',
labelText: 'Product price',
),
onChanged: (value) {
setState(() {
price = double.parse(value);
});
},
),
SizedBox(height: 16),
RaisedButton(
child: Text('Save'),
onPressed: () {
Product product = Product({
'name': name,
'description': description,
'price': price,
});
setState(() {
helper.createProduct(product);
Navigator.pop(context);
});
},
),
],
),
);
}
}
数据库操作
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sql_demo/models/product.dart';
class DbHelper {
//Creates a singleton class (it only creates once)
static final DbHelper _singleton = DbHelper._internal();
factory DbHelper() => _singleton;
DbHelper._internal();
//Creating an object of type database
static Database _database;
//Initializing or creating the database named mydb.db
//Creating a products table with necessary fields
Future<Database> initDatabase() async {
//If this class was never instaciated, we will execute this method, otherwise return
if (_database != null) return _database;
String path = join(await getDatabasesPath(), 'mydb.db');
_database = await openDatabase(
path,
version: 1,
onCreate: (Database db, int v) async {
await db.execute(
'CREATE TABLE Products (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, price REAL)');
},
);
return _database;
}
//Select all products
Future<List> getProducts() async {
Database db = await initDatabase();
return await db.query('Products');
}
//Create new product
Future<int> createProduct(Product product) async {
Database db = await initDatabase();
print('Product added');
return await db.insert(
'Products',
product.toMap(),
);
}
//Update product
Future<int> updateProduct(Product product) async {
Database db = await initDatabase();
return await db.update(
'Products',
product.toMap(),
where: 'id=?',
whereArgs: [product.id],
);
}
//Delete a product
Future<int> deleteProduct(int productID) async {
Database db = await initDatabase();
return await db.delete('Products', where: 'id=?', whereArgs: [productID]);
}
}
您可以复制粘贴 运行 下面的完整代码
您可以 await Navigator.push
到 AddProductPage
然后调用 setState(() {});
代码片段
onPressed: () async {
await Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
setState(() {});
}),
工作演示
完整代码
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:convert';
class Product {
int _id;
String _name;
String _description;
double _price;
//Getters because the attributes are private
int get id => _id;
String get name => _name;
String get description => _description;
double get price => _price;
//Constructor
Product(dynamic obj) {
_id = obj['id'];
_name = obj['name'];
_description = obj['description'];
_price = obj['price'];
}
//Named objet (takes a Map as parameter)
Product.fromMap(Map<String, dynamic> data) {
_id = data['id'];
_name = data['name'];
_description = data['description'];
_price = data['price'];
}
//Method that converts the object into a map
Map<String, dynamic> toMap() {
return {
'id': _id,
'name': _name,
'description': _description,
'price': _price,
};
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DbHelper helper;
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: FutureBuilder(
future: helper.getProducts(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Product product = Product.fromMap(snapshot.data[index]);
return ListTile(
contentPadding: const EdgeInsets.all(16.0),
title: Text(
'${product.name} - $${(product.price).toString()}'),
subtitle: Text(product.description),
trailing: Column(
children: [
Expanded(
child: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
setState(() {
helper.deleteProduct(product.id);
});
}),
),
SizedBox(
height: 20.0,
),
Expanded(
child: IconButton(
icon: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateProductPage(
product: product,
)),
);*/
}),
),
],
),
onTap: () {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsPage(
product: product,
)));*/
},
);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () async {
await Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
setState(() {});
}),
);
}
}
class AddProductPage extends StatefulWidget {
@override
_AddProductPageState createState() => _AddProductPageState();
}
class _AddProductPageState extends State<AddProductPage> {
String name, description;
num price;
DbHelper helper;
//Instantiate Helper
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add new product"),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product name',
labelText: 'Product name',
),
onChanged: (value) {
setState(() {
name = value;
});
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product description',
labelText: 'Product description',
),
onChanged: (value) {
setState(() {
description = value;
});
},
),
SizedBox(height: 16),
TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Enter product price',
labelText: 'Product price',
),
onChanged: (value) {
setState(() {
price = double.parse(value);
});
},
),
SizedBox(height: 16),
RaisedButton(
child: Text('Save'),
onPressed: () {
Product product = Product({
'name': name,
'description': description,
'price': price,
});
setState(() {
helper.createProduct(product);
Navigator.pop(context);
});
},
),
],
),
);
}
}
class DbHelper {
//Creates a singleton class (it only creates once)
static final DbHelper _singleton = DbHelper._internal();
factory DbHelper() => _singleton;
DbHelper._internal();
//Creating an object of type database
static Database _database;
//Initializing or creating the database named mydb.db
//Creating a products table with necessary fields
Future<Database> initDatabase() async {
//If this class was never instaciated, we will execute this method, otherwise return
if (_database != null) return _database;
String path = join(await getDatabasesPath(), 'mydb.db');
_database = await openDatabase(
path,
version: 1,
onCreate: (Database db, int v) async {
await db.execute(
'CREATE TABLE Products (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, price REAL)');
},
);
return _database;
}
//Select all products
Future<List> getProducts() async {
Database db = await initDatabase();
return await db.query('Products');
}
//Create new product
Future<int> createProduct(Product product) async {
Database db = await initDatabase();
print('Product added');
return await db.insert(
'Products',
product.toMap(),
);
}
//Update product
Future<int> updateProduct(Product product) async {
Database db = await initDatabase();
return await db.update(
'Products',
product.toMap(),
where: 'id=?',
whereArgs: [product.id],
);
}
//Delete a product
Future<int> deleteProduct(int productID) async {
Database db = await initDatabase();
return await db.delete('Products', where: 'id=?', whereArgs: [productID]);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
Hot reload:Hot reload 特性快速编译我们文件中新添加的代码并将代码发送到 Dart 虚拟机。如果您在应用程序中使用状态,则热重载会保留状态,因此它们不会在热重载时将我们的设置更新为默认值。
并且,initState()
不会在热重载后重建,因为它的状态已保留。因此,您必须执行热重启才能看到数据库更改:
@override
void initState() {
super.initState();
helper = DbHelper();
}
构建有状态小部件时,您有 helper
,但在热重新加载后,助手将与 initState
相同,仅调用热重启或启动小部件。因此,helper
变量被保留。因此,您必须热重启。
可能对您有帮助的链接:Understanding Flutter hot reload and hot restart the simplest way | Refs
我正在学习 Flutter,我正在尝试使用 SQFLite 包在设备上保存数据。一切正常,但有一个问题,每次我添加一个新元素或升级它时,我都需要重新启动我的应用程序才能看到更改,我不知道为什么,没有错误或任何东西。 我把它上传到 github 所以你可以试试,也许是我的模拟器里的东西或者我不知道的东西。 https://github.com/Rodrigogzmn6/sql_demo
或者您可以在此处查看完整项目的一部分
主页
import 'package:flutter/material.dart';
import 'package:sql_demo/models/product.dart';
import 'package:sql_demo/pages/add_product_page.dart';
import 'package:sql_demo/pages/update_product_page.dart';
import 'package:sql_demo/pages/view_product_page.dart';
import 'package:sql_demo/services/dbhelper.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DbHelper helper;
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: FutureBuilder(
future: helper.getProducts(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Product product = Product.fromMap(snapshot.data[index]);
return ListTile(
contentPadding: const EdgeInsets.all(16.0),
title: Text(
'${product.name} - $${(product.price).toString()}'),
subtitle: Text(product.description),
trailing: Column(
children: [
Expanded(
child: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
setState(() {
helper.deleteProduct(product.id);
});
}),
),
SizedBox(
height: 20.0,
),
Expanded(
child: IconButton(
icon: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateProductPage(
product: product,
)),
);
}),
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsPage(
product: product,
)));
},
);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
}),
);
}
}
正在创建项目页面
import 'package:flutter/material.dart';
import 'package:sql_demo/models/product.dart';
import 'package:sql_demo/services/dbhelper.dart';
class AddProductPage extends StatefulWidget {
@override
_AddProductPageState createState() => _AddProductPageState();
}
class _AddProductPageState extends State<AddProductPage> {
String name, description;
num price;
DbHelper helper;
//Instantiate Helper
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add new product"),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product name',
labelText: 'Product name',
),
onChanged: (value) {
setState(() {
name = value;
});
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product description',
labelText: 'Product description',
),
onChanged: (value) {
setState(() {
description = value;
});
},
),
SizedBox(height: 16),
TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Enter product price',
labelText: 'Product price',
),
onChanged: (value) {
setState(() {
price = double.parse(value);
});
},
),
SizedBox(height: 16),
RaisedButton(
child: Text('Save'),
onPressed: () {
Product product = Product({
'name': name,
'description': description,
'price': price,
});
setState(() {
helper.createProduct(product);
Navigator.pop(context);
});
},
),
],
),
);
}
}
数据库操作
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sql_demo/models/product.dart';
class DbHelper {
//Creates a singleton class (it only creates once)
static final DbHelper _singleton = DbHelper._internal();
factory DbHelper() => _singleton;
DbHelper._internal();
//Creating an object of type database
static Database _database;
//Initializing or creating the database named mydb.db
//Creating a products table with necessary fields
Future<Database> initDatabase() async {
//If this class was never instaciated, we will execute this method, otherwise return
if (_database != null) return _database;
String path = join(await getDatabasesPath(), 'mydb.db');
_database = await openDatabase(
path,
version: 1,
onCreate: (Database db, int v) async {
await db.execute(
'CREATE TABLE Products (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, price REAL)');
},
);
return _database;
}
//Select all products
Future<List> getProducts() async {
Database db = await initDatabase();
return await db.query('Products');
}
//Create new product
Future<int> createProduct(Product product) async {
Database db = await initDatabase();
print('Product added');
return await db.insert(
'Products',
product.toMap(),
);
}
//Update product
Future<int> updateProduct(Product product) async {
Database db = await initDatabase();
return await db.update(
'Products',
product.toMap(),
where: 'id=?',
whereArgs: [product.id],
);
}
//Delete a product
Future<int> deleteProduct(int productID) async {
Database db = await initDatabase();
return await db.delete('Products', where: 'id=?', whereArgs: [productID]);
}
}
您可以复制粘贴 运行 下面的完整代码
您可以 await Navigator.push
到 AddProductPage
然后调用 setState(() {});
代码片段
onPressed: () async {
await Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
setState(() {});
}),
工作演示
完整代码
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:convert';
class Product {
int _id;
String _name;
String _description;
double _price;
//Getters because the attributes are private
int get id => _id;
String get name => _name;
String get description => _description;
double get price => _price;
//Constructor
Product(dynamic obj) {
_id = obj['id'];
_name = obj['name'];
_description = obj['description'];
_price = obj['price'];
}
//Named objet (takes a Map as parameter)
Product.fromMap(Map<String, dynamic> data) {
_id = data['id'];
_name = data['name'];
_description = data['description'];
_price = data['price'];
}
//Method that converts the object into a map
Map<String, dynamic> toMap() {
return {
'id': _id,
'name': _name,
'description': _description,
'price': _price,
};
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
DbHelper helper;
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: FutureBuilder(
future: helper.getProducts(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Product product = Product.fromMap(snapshot.data[index]);
return ListTile(
contentPadding: const EdgeInsets.all(16.0),
title: Text(
'${product.name} - $${(product.price).toString()}'),
subtitle: Text(product.description),
trailing: Column(
children: [
Expanded(
child: IconButton(
icon: Icon(
Icons.delete,
color: Colors.red,
),
onPressed: () {
setState(() {
helper.deleteProduct(product.id);
});
}),
),
SizedBox(
height: 20.0,
),
Expanded(
child: IconButton(
icon: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpdateProductPage(
product: product,
)),
);*/
}),
),
],
),
onTap: () {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsPage(
product: product,
)));*/
},
);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () async {
await Navigator.push(context,
MaterialPageRoute(builder: (context) => AddProductPage()));
setState(() {});
}),
);
}
}
class AddProductPage extends StatefulWidget {
@override
_AddProductPageState createState() => _AddProductPageState();
}
class _AddProductPageState extends State<AddProductPage> {
String name, description;
num price;
DbHelper helper;
//Instantiate Helper
@override
void initState() {
super.initState();
helper = DbHelper();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add new product"),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product name',
labelText: 'Product name',
),
onChanged: (value) {
setState(() {
name = value;
});
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
hintText: 'Enter product description',
labelText: 'Product description',
),
onChanged: (value) {
setState(() {
description = value;
});
},
),
SizedBox(height: 16),
TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Enter product price',
labelText: 'Product price',
),
onChanged: (value) {
setState(() {
price = double.parse(value);
});
},
),
SizedBox(height: 16),
RaisedButton(
child: Text('Save'),
onPressed: () {
Product product = Product({
'name': name,
'description': description,
'price': price,
});
setState(() {
helper.createProduct(product);
Navigator.pop(context);
});
},
),
],
),
);
}
}
class DbHelper {
//Creates a singleton class (it only creates once)
static final DbHelper _singleton = DbHelper._internal();
factory DbHelper() => _singleton;
DbHelper._internal();
//Creating an object of type database
static Database _database;
//Initializing or creating the database named mydb.db
//Creating a products table with necessary fields
Future<Database> initDatabase() async {
//If this class was never instaciated, we will execute this method, otherwise return
if (_database != null) return _database;
String path = join(await getDatabasesPath(), 'mydb.db');
_database = await openDatabase(
path,
version: 1,
onCreate: (Database db, int v) async {
await db.execute(
'CREATE TABLE Products (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, price REAL)');
},
);
return _database;
}
//Select all products
Future<List> getProducts() async {
Database db = await initDatabase();
return await db.query('Products');
}
//Create new product
Future<int> createProduct(Product product) async {
Database db = await initDatabase();
print('Product added');
return await db.insert(
'Products',
product.toMap(),
);
}
//Update product
Future<int> updateProduct(Product product) async {
Database db = await initDatabase();
return await db.update(
'Products',
product.toMap(),
where: 'id=?',
whereArgs: [product.id],
);
}
//Delete a product
Future<int> deleteProduct(int productID) async {
Database db = await initDatabase();
return await db.delete('Products', where: 'id=?', whereArgs: [productID]);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
Hot reload:Hot reload 特性快速编译我们文件中新添加的代码并将代码发送到 Dart 虚拟机。如果您在应用程序中使用状态,则热重载会保留状态,因此它们不会在热重载时将我们的设置更新为默认值。
并且,initState()
不会在热重载后重建,因为它的状态已保留。因此,您必须执行热重启才能看到数据库更改:
@override
void initState() {
super.initState();
helper = DbHelper();
}
构建有状态小部件时,您有 helper
,但在热重新加载后,助手将与 initState
相同,仅调用热重启或启动小部件。因此,helper
变量被保留。因此,您必须热重启。
可能对您有帮助的链接:Understanding Flutter hot reload and hot restart the simplest way | Refs