Results show
Storage data through the local database, your car 🚗 into the local, and through the status management refresh page, you can control the vehicle start state (read and write database)
Preface 📌
Recently due to business needs, I began to study the local data store Flutter, to do a good job in the local data storage is the most important is to have a basic understanding of the database, database construction, built form, add and delete, are basic database operations, you before must have certain knowledge of the database, or you will see the fog 😅.
Small instructions 🤠
In fact, only on the local storage of the database, a rough think will feel ~ very simple 😑, nothing can learn the point. The actual hands-on code to write a demo is also very simple, you can easily do a series of operations such as building a library, but this article is to do these seemingly simple operations and the actual business combined, specific to buckle the details, I believe that there will be a lot of harvest after reading 🎉.
Technology selection
We are inFlutter
When operating a database, our primary purpose must be that we need to do some operations on some data (with a certain amount of data, not lightweight) data, then what is the purpose of our operation? Must be to meet the needs of users, all kinds of data display 💡! So how do we present our data more elegantly? In other words, how can we be as sure as possible when working with the databaseFlutter
Rendering performance? This can not do withoutFlutter
State management. There are many solutions for state management, and I personally saw a lot of adoption while studying this sectionbloc
But my business projects have been adopted in the early stageprovider
How do you do that 👀, then you can only study ~. Once I’ve defined my state management plan, it’s time to pick and chooseplugin
.provider
As an official plugin, the priority goes without saying. What about databases? After comprehensive consideration, our database is adoptedSQLite
One may ask, what is the overall consideration? 🤯, do you have to ask?High heat ➕ highLikes
➕ Flutter Favorite
. Saliva does not contend with the flow out of the mouth, too sweet 👀
database
(Database) :SQLite
–sqflite
- State management:
provider
–provider
Start building, step by step
Step 1: Be prepared 💪
We will first build a new project, in which we will add the three party libraries we will use in our project:
sqflite: ^ 1.3.1
provider: ^ 4.3.2
path_provider: ^ 1.6.11
Copy the code
path_provider
: Used to obtain the local storage path
The second step: from simple to complex 📈
So the first step is we’re going to see a project like this, and we’re going to store the database, so what’s the first thing we need? Is a data structure for both our read and write operations. This data structure is our 🚗 data structure. We want to have various attributes: the make of the car, the model of the car, whether it starts or not. There is an ID, convenient for our reading, in fact, familiar with the database students should also be able to think of this ID, is our primary key 🐳.
class Car {
int id;
String brand;
String type;
bool start;
Car({@required this.brand, this.type, this.start = false});
Map<String.dynamic> toMap() {
var map = Map<String.dynamic> ();if(id ! =null) {
map['id'] = id;
}
map['brand'] = brand;
map['type'] = type;
map['start'] = start == true ? 1 : 0;
return map;
}
Car.fromMapObject(Map<String.dynamic> map) {
this.id = map['id'];
this.brand = map['brand'];
this.type = map['type'];
this.start = map['start'] = =1 ? true : false; }}Copy the code
Step 3: Critical database operations 🏄🏻♂️
Now, the next step is critical, and it fits in with the theme of the day. Our database operations include database creation, table creation, add, delete, change and check, these basic operations, we go to the UI layer to write our structure looks very messy 🤯, and the reuse is very poor, so here we take a separate class, wrapper, I call it DatabaseHelper. Thanks to our powerful plug-ins, we only need to deal with the upper level API 🤠, the lower level multi-terminal operations are already encapsulated.
void _createDb(Database db, int newVersion) async {
await db.execute(
'CREATE TABLE $carsTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colBrand TEXT, $colType TEXT, $colStart INTEGER)');
}
// Read data
Future<List<Map<String.dynamic>>> getCarMapList() async {
Database db = await this.database;
var result = await db.query(carsTable);
return result;
}
// Add data
Future<int> insertCar(Car car) async {
Database db = await this.database;
var result = await db.insert(carsTable, car.toMap());
return result;
}
// Refresh data
Future<int> updateCar(Car car) async {
Database db = await this.database;
var result = await db.update(carsTable, car.toMap(),
where: '$colId = ?', whereArgs: [car.id]);
return result;
}
// Delete data
Future<int> deleteCar(int id) async {
Database db = await this.database;
int result =
await db.rawDelete('DELETE FROM $carsTable WHERE $colId = $id');
return result;
}
Copy the code
Step 4: Equally critical state management 🔮
This step is also our core, how we can combine the data in our database with the UI part and properly control the render scope 🖼, as complicated as it sounds, we can think of several core points, bit by bit to make up our part ⚒.
- First of all, choose
provider
As state management, we traditionally want to encapsulate ourprovider
Class withChangeNotifier
. - We need multiple methods with state changes, and in each method we need to notify refresh, or join
notifyListeners()
Methods. - We need to figure out what methods we need: add data, modify data, subtract data, read data.
I believe that with the above points, you see the following code will have more ideas 😁 :
class CarsProvider with ChangeNotifier {
DatabaseHelper _databaseHelper = DatabaseHelper();
List<Car> _cars;
int _count = 0;
UnmodifiableListView<Car> get allCars => UnmodifiableListView(_cars);
UnmodifiableListView<Car> get unStartedCars =>
UnmodifiableListView(_cars.where((car) => car.start == false));
UnmodifiableListView<Car> get startedCars =>
UnmodifiableListView(_cars.where((car) => car.start == true));
void getCarList() {
final Future<Database> dbFuture = _databaseHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Car>> carListFuture = _databaseHelper.getCarList();
carListFuture.then((carList) {
this._cars = carList;
this._count = carList.length;
notifyListeners();
});
});
}
int get count => _count;
void addCar(Car car) async {
int result;
if(car.id ! =null) {
result = await _databaseHelper.updateCar(car);
} else {
result = await _databaseHelper.insertCar(car);
}
if(result ! =0) {
print('Success');
} else {
print('Failed');
}
notifyListeners();
}
void startCar(BuildContext context, Car car) async{ car.start = ! car.start;int result = await _databaseHelper.updateCar(car);
if(result ! =0 && car.start == true) {
_showSnackBar(context, '${car.brand}' +' '+'${car.type}' + ' ' +'Start');
}
notifyListeners();
}
void deleteCar(BuildContext context, Car car) async {
if (car.id == null) {
_showSnackBar(context, 'No Car was deleted');
return;
}
int result = await _databaseHelper.deleteCar(car.id);
if(result ! =0) {
_showSnackBar(context, 'Car Deleted Successfully');
} else {
_showSnackBar(context, 'Error Occurred while deleting note');
}
notifyListeners();
}
void _showSnackBar(BuildContext context, String message) {
final snackBar = SnackBar(
duration: Duration(milliseconds: 500), content: Text( message, style: TextStyle(color: Colors.white), ), backgroundColor: Theme.of(context).primaryColor, ); Scaffold.of(context).showSnackBar(snackBar); }}Copy the code
Step 5: Enrich the UI content 🎁
In fact, the above two sections are our core, if you can understand the above two core classes, I will throw out some UI-level operations you should understand 🚀. Here I will show you an operation to add vehicles. More content can be viewed at the end of the source.
// Add a new car
void onAdd() {
if (carBrandController.text.isNotEmpty && carTypeController.text.isNotEmpty ) {
final Car car = Car(brand: carBrandController.text, type:carTypeController.text, start: started);
Provider.of<CarsProvider>(context, listen: false).addCar(car); Navigator.pop(context); }}Copy the code
Conclusion and Prospect
When we learn some content sometimes feel very simple, the actual start or have a lot of difficulties, encounter problems timely solution is very important ⚙️. Every time I touch the new knowledge of Flutter, I will gain something 🎊. I will try my best to sort out what I have learned. For me, on the one hand, this strengthens my memory and deepens my understanding, and on the other hand, it can help my friends who encounter related problems. Welcome to my blog at 🤝.
The source code
Strongly suggest to a 🌟 to encourage the author, ha ha ha ha ha ha ha: this article demo