为什么我必须执行热重启才能在 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.pushAddProductPage 然后调用 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