باستخدام سكليتي في الرفرفة

مرحبا يا هبر! نقدم انتباهكم ترجمة لمقال "استخدام SQLite في الرفرفة" .



يعد حفظ البيانات مهمًا جدًا للمستخدمين ، لأنه من غير العملي تحميل نفس البيانات من الشبكة. سيكون أكثر حكمة لإنقاذهم محليا.

في هذه المقالة ، سأشرح كيفية القيام بذلك باستخدام SQLite في Flutter-e

لماذا سكليتي؟


SQLite هي الطريقة الأكثر شعبية لتخزين البيانات على الأجهزة المحمولة. في هذه المقالة ، سوف نستخدم حزمة sqflite لاستخدام SQLite. Sqflite هي واحدة من المكتبات الأكثر استخدامًا وذات الصلة لتوصيل قواعد بيانات SQLite بالرفرفة.

1. إضافة التبعيات


في مشروعنا ، افتح ملف pubspec.yaml . ضمن التبعيات ، أضف أحدث إصدار من sqflite و path_provider.

dependencies: flutter: sdk: flutter sqflite: any path_provider: any 

2. إنشاء عميل DB


الآن إنشاء ملف Database.dart جديد. في ذلك ، إنشاء مفردة.

لماذا نحتاج إلى حرف مفرد: نستخدم هذا النمط للتأكد من أن لدينا كيانًا صنفًا واحدًا فقط ونوفر نقطة دخول عالمية فيه.

1. قم بإنشاء مُنشئ خاص لا يمكن استخدامه إلا داخل هذه الفئة.

 class DBProvider { DBProvider._(); static final DBProvider db = DBProvider._(); } 

2. إعداد قاعدة البيانات

الخطوة التالية هي إنشاء كائن قاعدة البيانات وتوفير getter حيث سنقوم بإنشاء كائن قاعدة البيانات إذا لم يتم إنشاؤه بعد (التهيئة البطيئة)

 static Database _database; Future<Database> get database async { if (_database != null) return _database; // if _database is null we instantiate it _database = await initDB(); return _database; } 

إذا لم يكن هناك كائن معين لقاعدة البيانات ، فسنقوم باستدعاء دالة initDB لإنشاء قاعدة البيانات. في هذه الوظيفة ، نحصل على المسار لحفظ قاعدة البيانات وإنشاء الجداول المطلوبة

 initDB() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, "TestDB.db"); return await openDatabase(path, version: 1, onOpen: (db) { }, onCreate: (Database db, int version) async { await db.execute("CREATE TABLE Client (" "id INTEGER PRIMARY KEY," "first_name TEXT," "last_name TEXT," "blocked BIT" ")"); }); } 

3. إنشاء فئة النموذج


سيتم تحويل البيانات الموجودة داخل قاعدة البيانات إلى خرائط Dart. نحن بحاجة إلى إنشاء فئات نموذجية باستخدام أساليب toMap و fromMap.

لإنشاء فئات نموذجية ، سأستخدم هذا الموقع

نموذجنا:

 /// ClientModel.dart import 'dart:convert'; Client clientFromJson(String str) { final jsonData = json.decode(str); return Client.fromJson(jsonData); } String clientToJson(Client data) { final dyn = data.toJson(); return json.encode(dyn); } class Client { int id; String firstName; String lastName; bool blocked; Client({ this.id, this.firstName, this.lastName, this.blocked, }); factory Client.fromJson(Map<String, dynamic> json) => new Client( id: json["id"], firstName: json["first_name"], lastName: json["last_name"], blocked: json["blocked"], ); Map<String, dynamic> toJson() => { "id": id, "first_name": firstName, "last_name": lastName, "blocked": blocked, }; } 

4. عمليات CRUD


خلق

باستخدام rawInsert:

 newClient(Client newClient) async { final db = await database; var res = await db.rawInsert( "INSERT Into Client (id,first_name)" " VALUES (${newClient.id},${newClient.firstName})"); return res; } 

باستخدام إدراج:

 newClient(Client newClient) async { final db = await database; var res = await db.insert("Client", newClient.toMap()); return res; } 

مثال آخر باستخدام معرف كبير كمعرف جديد

 newClient(Client newClient) async { final db = await database; //get the biggest id in the table var table = await db.rawQuery("SELECT MAX(id)+1 as id FROM Client"); int id = table.first["id"]; //insert to the table using the new id var raw = await db.rawInsert( "INSERT Into Client (id,first_name,last_name,blocked)" " VALUES (?,?,?,?)", [id, newClient.firstName, newClient.lastName, newClient.blocked]); return raw; } 

قراءة

الحصول على العميل بواسطة معرف

 getClient(int id) async { final db = await database; var res =await db.query("Client", where: "id = ?", whereArgs: [id]); return res.isNotEmpty ? Client.fromMap(res.first) : Null ; } 

الحصول على جميع العملاء مع حالة

 getAllClients() async { final db = await database; var res = await db.query("Client"); List<Client> list = res.isNotEmpty ? res.map((c) => Client.fromMap(c)).toList() : []; return list; } 

احصل على العملاء المحظورين فقط

 getBlockedClients() async { final db = await database; var res = await db.rawQuery("SELECT * FROM Client WHERE blocked=1"); List<Client> list = res.isNotEmpty ? res.toList().map((c) => Client.fromMap(c)) : null; return list; } 

تحديث

تحديث عميل موجود

 updateClient(Client newClient) async { final db = await database; var res = await db.update("Client", newClient.toMap(), where: "id = ?", whereArgs: [newClient.id]); return res; } 

قفل العميل / فتح

 blockOrUnblock(Client client) async { final db = await database; Client blocked = Client( id: client.id, firstName: client.firstName, lastName: client.lastName, blocked: !client.blocked); var res = await db.update("Client", blocked.toMap(), where: "id = ?", whereArgs: [client.id]); return res; } 

حذف

حذف عميل واحد

 deleteClient(int id) async { final db = await database; db.delete("Client", where: "id = ?", whereArgs: [id]); } 

حذف جميع العملاء

 deleteAll() async { final db = await database; db.rawDelete("Delete * from Client"); } 

عرض



بالنسبة إلى العرض التوضيحي الخاص بنا ، سنقوم بإنشاء تطبيق بسيط يعرض قاعدة البيانات الخاصة بنا.

أولاً نصنع الشاشة

 Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Flutter SQLite")), body: FutureBuilder<List<Client>>( future: DBProvider.db.getAllClients(), builder: (BuildContext context, AsyncSnapshot<List<Client>> snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data.length, itemBuilder: (BuildContext context, int index) { Client item = snapshot.data[index]; return ListTile( title: Text(item.lastName), leading: Text(item.id.toString()), trailing: Checkbox( onChanged: (bool value) { DBProvider.db.blockClient(item); setState(() {}); }, value: item.blocked, ), ); }, ); } else { return Center(child: CircularProgressIndicator()); } }, ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () async { Client rnd = testClients[math.Random().nextInt(testClients.length)]; await DBProvider.db.newClient(rnd); setState(() {}); }, ), ); } 

ملاحظات:

1. يستخدم FutureBuilder للحصول على البيانات من قاعدة البيانات

2. FAB لتهيئة عملاء الاختبار

 List<Client> testClients = [ Client(firstName: "Raouf", lastName: "Rahiche", blocked: false), Client(firstName: "Zaki", lastName: "oun", blocked: true), Client(firstName: "oussama", lastName: "ali", blocked: false), ]; 

3. يظهر CircularProgressIndicator عند عدم وجود بيانات.

4. عندما ينقر المستخدم على مربعات الاختيار ، يتم حظر / إلغاء قفل العميل

الآن أصبح من السهل جدًا إضافة ميزات جديدة ، على سبيل المثال ، إذا كنا نريد إزالة العميل عند التمرير السريع ، فقم فقط بلف ListTile في عنصر واجهة مستخدم غير قابل للإزالة مثل هذا:

 return Dismissible( key: UniqueKey(), background: Container(color: Colors.red), onDismissed: (direction) { DBProvider.db.deleteClient(item.id); }, child: ListTile(...), ); 


Refactoring لاستخدام نمط BLoC


لقد قمنا بالكثير في هذه المقالة ، ولكن في التطبيقات الواقعية ، فإن تهيئة الدول في طبقة واجهة المستخدم ليست فكرة جيدة. افصل المنطق عن واجهة المستخدم.

هناك العديد من الأنماط في Flutter ، لكننا سنستخدم BLoC لأنه الأكثر مرونة في التخصيص.

إنشاء BLOC

 class ClientsBloc { ClientsBloc() { getClients(); } final _clientController = StreamController<List<Client>>.broadcast(); get clients => _clientController.stream; dispose() { _clientController.close(); } getClients() async { _clientController.sink.add(await DBProvider.db.getAllClients()); } } 

ملاحظات:
ملاحظات:

1. يتلقى getClients البيانات من قاعدة البيانات (جدول العميل) بشكل غير متزامن. سوف نستخدم هذه الطريقة كلما احتجنا إلى تحديث الجدول ، لذلك يجدر وضعه في نص المنشئ.

2. أنشأنا StreamController.broadcast من أجل الاستماع إلى أحداث البث أكثر من مرة. في مثالنا ، هذا لا يهم حقًا ، حيث أننا نستمع إليهم مرة واحدة فقط ، لكن سيكون من الجيد تنفيذ ذلك للمستقبل.

3. لا تنس أن تغلق المواضيع. بهذه الطريقة سنمنع النصب التذكارية. في مثالنا ، نقوم بإغلاقها باستخدام طريقة التخلص في StatefulWidget

الآن انظر إلى الكود

 blockUnblock(Client client) { DBProvider.db.blockOrUnblock(client); getClients(); } delete(int id) { DBProvider.db.deleteClient(id); getClients(); } add(Client client) { DBProvider.db.newClient(client); getClients(); } 

وأخيرا النتيجة النهائية


يمكن العثور على المصادر هنا - جيثب

Source: https://habr.com/ru/post/ar435418/


All Articles