flutter 數(shù)據(jù)庫
This article was originally published here on the Codemagic blog
本文最初發(fā)布在 Codemagic博客 上
There are a lot of options out there today when it comes to databases in your application. They typically fit into these three categories:
對于應(yīng)用程序中的數(shù)據(jù)庫芳杏,今天有很多選擇。 它們通常適合以下三類:
-
Relational — these are the databases in the traditional sense. They don’t just store data but also the relationships between the data. SQLite is an example of a relational database.
關(guān)系式 -這些是傳統(tǒng)意義上的數(shù)據(jù)庫勒虾。 它們不僅存儲數(shù)據(jù)县踢,還存儲數(shù)據(jù)之間的關(guān)系 。 SQLite是關(guān)系數(shù)據(jù)庫的一個(gè)示例。
-
NoSQL — these databases store data as documents. A schema is not enforced as is the case with a relational database. They are lightning-quick and handle huge unstructured pieces of data very well. MongoDB is an example of a NoSQL database.
NoSQL-這些數(shù)據(jù)庫將數(shù)據(jù)存儲為文檔 戈毒。 與關(guān)系數(shù)據(jù)庫不同艰猬,沒有強(qiáng)制執(zhí)行架構(gòu)。 它們閃電般迅捷 埋市,可以很好地處理大量非結(jié)構(gòu)化數(shù)據(jù)冠桃。 MongoDB是NoSQL數(shù)據(jù)庫的示例。
-
Individually tailored data storage — while this option is not technically a database, you don’t have to use the above solutions. You can store your data in a JSON file and handle the serialisation and deserialisation yourself. This would be incredibly fast but would open you up to some weird bugs if you weren’t a programming genius. ??
量身定制的數(shù)據(jù)存儲 -盡管從技術(shù)上講該選項(xiàng)不是數(shù)據(jù)庫道宅,但您不必使用上述解決方案食听。 您可以將數(shù)據(jù)存儲在JSON文件中,并親自處理序列化和反序列化污茵。 這將是非秤1ǎ快的,但是如果您不是編程天才省咨,則會(huì)使您遇到一些奇怪的錯(cuò)誤肃弟。 ??
By the end of this article, you will know:
到本文結(jié)尾,您將知道:
- The basics of how each database works. ??
每個(gè)數(shù)據(jù)庫的工作原理零蓉。 ?? - How to get set up with each database. ?
如何建立每個(gè)數(shù)據(jù)庫笤受。 ? - What a good use case would be for each database. ??
每個(gè)數(shù)據(jù)庫都有一個(gè)很好的用例。 ??
In this article, we’ll divide our database types according to the three categories mentioned above.
在本文中敌蜂,我們將根據(jù)上述三個(gè)類別來劃分?jǐn)?shù)據(jù)庫類型箩兽。
關(guān)系型 (Relational)
Relational databases have been around for a very long time (since 1970, according to a quick Google search). Let’s look at some of the options you have on Flutter for relational databases today.
關(guān)系數(shù)據(jù)庫已經(jīng)存在很長時(shí)間了(根據(jù)Google的快速搜索,自1970年以來)章喉。 讓我們看看您在Flutter上為關(guān)系數(shù)據(jù)庫所擁有的一些選項(xiàng)汗贫。
SQflite (SQflite)
SQflite is an implementation of SQLite for Flutter. It affords you complete control over your database, queries, relationships, everything you could wish for.
SQflite是SQLite for Flutter的實(shí)現(xiàn)。 它使您可以完全控制數(shù)據(jù)庫秸脱,查詢落包,關(guān)系以及所有想要的東西。
Interacting with a SQLite database in Flutter looks like this (from the docs):
在Flutter中與SQLite數(shù)據(jù)庫進(jìn)行交互看起來像這樣( 來自docs ):
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'demo.db');
// Delete the database
await deleteDatabase(path);
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)');
});
Inserting data follows the same age-old SQLite tenants
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)');
print('inserted1: $id1');
int id2 = await txn.rawInsert(
'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)',
['another name', 12345678, 3.1416]); print('inserted2: $id2');
});
And querying happens like this:
查詢發(fā)生如下:
// Get the records
List<Map> list = await database.rawQuery('SELECT * FROM Test');
優(yōu)點(diǎn)?? (Pros ??)
- Total control over the database.
完全控制數(shù)據(jù)庫摊唇。 - A very efficient SQLite database for your app (given that you have pre-existing SQLite knowledge).
適用于您應(yīng)用的高效SQLite數(shù)據(jù)庫(前提是您已具備SQLite知識)咐蝇。 - Easily read by third party apps that can open SQLite databases (so you can open the database on your computer and see what the data looks like).
可以打開SQLite數(shù)據(jù)庫的第三方應(yīng)用程序可以輕松讀取(因此您可以在計(jì)算機(jī)上打開數(shù)據(jù)庫,查看數(shù)據(jù)是什么樣的)巷查。
缺點(diǎn)?? (Cons ??)
- Writing out all your queries by hand can take a lot of time.
手工寫出所有查詢會(huì)花費(fèi)很多時(shí)間有序。 - Returned data from the database isn’t strongly typed from the start.
從數(shù)據(jù)庫開始返回的數(shù)據(jù)從一開始就不是強(qiáng)類型的。 - It is potentially difficult to handle migrations on the device (when the schema changes between version updates for instance).
處理設(shè)備上的遷移可能很困難(例如岛请,當(dāng)模式在版本更新之間更改時(shí))旭寿。 - It has no support for web.
它不支持網(wǎng)絡(luò)。
用例 (Use case)
SQFlite is good when you need relational data but also fine-grained control over the actual queries. If you’re comfortable with writing your own queries and don’t mind writing both a lot of queries and the code to convert the results to and from your classes, this could be a good fit for you.
當(dāng)您需要關(guān)系數(shù)據(jù)時(shí)崇败,SQFlite是很好的選擇盅称,而且還可以對實(shí)際查詢進(jìn)行細(xì)粒度的控制。 如果您對編寫自己的查詢感到滿意,并且不介意編寫大量查詢和將結(jié)果與類進(jìn)行相互轉(zhuǎn)換的代碼缩膝,那么這可能非常適合您搭幻。
SQLite抽象 (SQLite abstractions)
Directly using SQLite to manage your application database can be quite powerful but also unwieldy. That’s why there are so many solutions that abstract some of the functionality from SQLite into more easily used functionality. These abstractions can make a SQLite database easier to use, while still retaining a lot of the benefits of SQLite.
直接使用SQLite管理您的應(yīng)用程序數(shù)據(jù)庫可能非常強(qiáng)大,但也很麻煩逞盆。 這就是為什么有這么多解決方案將SQLite的某些功能抽象為更易于使用的功能的原因。 這些抽象可以使SQLite數(shù)據(jù)庫更易于使用松申,同時(shí)仍然保留SQLite的許多優(yōu)點(diǎn)云芦。
Floor and Moor are fairly popular examples of this approach. In this article we’ll look at Moor, but the approach that these two packages take in abstracting SQLite is fairly similar.
Floor和Moor是這種方法相當(dāng)受歡迎的示例。 在本文中贸桶,我們將探討Moor舅逸,但是這兩個(gè)軟件包在抽象SQLite中所采用的方法非常相似。
泊 (Moor)
In order to use Moor, we import the Moor package from flutter pub, but we also have to import something called the moor_generator
. This is used by build_runner
to generate the code to use the database.
為了使用Moor皇筛,我們從flutter pub導(dǎo)入了Moor包琉历,但是我們還必須導(dǎo)入一個(gè)稱為moor_generator
東西。 build_runner
使用build_runner
來生成使用數(shù)據(jù)庫的代碼水醋。
Why do we use
build_runner
?build_runner
is primarily used to generate code for your Flutter projects. Before I came to Flutter, I rarely, if ever, had to use a code generation utility. The main reason for this is because most other languages that I had used up until this point (such as C#) supported reflection.為什么我們使用
build_runner
旗笔?build_runner
主要用于 為Flutter項(xiàng)目 生成代碼。在來Flutter之前拄踪,我很少(如果有的話)必須使用代碼生成實(shí)用程序蝇恶。這樣做的主要原因是因?yàn)榈侥壳盀橹刮矣帽M的其他大多數(shù)語言(例如C#)都支持反射。Simply put, this makes it possible for the framework to dynamically invoke parts of the program at runtime. It’s quite powerful, but typically it can be quite slow. It also affects linking of the produced application, as with reflection, technically every part of your application could be accessed or used.
簡而言之惶桐,這使框架可以在運(yùn)行時(shí)動(dòng)態(tài)調(diào)用程序的各個(gè)部分撮弧。 它功能強(qiáng)大,但通常速度可能很慢姚糊。 它也影響 生成的應(yīng)用程序的 鏈接 贿衍,就像反射一樣,從技術(shù)上講救恨,您的應(yīng)用程序的每個(gè)部分都可以訪問或使用贸辈。
When packages use functionality that typically were provided by reflection, they usually use
build_runner
to generate the necessary code ahead of time. This results in faster code execution at runtime, and also results in better ‘tree shaking’, or minimisation of the application binary at deployment time.當(dāng)程序包使用通常由反射提供的功能時(shí),它們通常使用
build_runner
提前生成必要的代碼忿薇。 這樣可以在運(yùn)行時(shí)更快地執(zhí)行代碼裙椭,還可以在部署時(shí)更好地“搖樹”或最小化應(yīng)用程序二進(jìn)制文件。
A look into the Getting Started documentation helps us understand the way a database is created.
查看“入門”文檔可幫助我們了解創(chuàng)建數(shù)據(jù)庫的方式署浩。
import 'package:moor/moor.dart';
// assuming that your file is called filename.dart. This will give an error at first,
// but it's needed for moor to know about the generated codepart 'filename.g.dart';
// this will generate a table called "todos" for us. The rows of that table will
// be represented by a class called "Todo".
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 32)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
}
// This will make moor generate a class called "Category" to represent a row in this table.
// By default, "Categorie" would have been used because it strips away the trailing "s"
// in the table name.
@DataClassName("Category")
class Categories extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get description => text()();
}
// this annotation tells moor to prepare a database class that uses both tables
// we just defined. We'll see how to use that database class in a moment.
@UseMoor(tables: [Todos, Categories])
class MyDatabase { }
Moor programatically creates the schema for your tables depending on how you define their contents. In the beginning of this code example, we can see the part
statement. When we run the build_runner
command, moor
generates the schema based on what we have defined in this file. You can also drop back to raw SQL at any time if you need to run a specific query or if you want more fine-grained control.
Moor通過編程方式為您的表創(chuàng)建架構(gòu)揉燃,具體取決于您定義表內(nèi)容的方式。 在此代碼示例的開頭筋栋,我們可以看到part
語句炊汤。 當(dāng)我們運(yùn)行build_runner
命令時(shí), moor
根據(jù)我們在此文件中定義的內(nèi)容生成架構(gòu)。 如果需要運(yùn)行特定查詢或需要更細(xì)粒度的控制抢腐,則還可以隨時(shí)返回原始SQL姑曙。
優(yōu)點(diǎn)?? (Pros ??)
-
Strongly typed results!
強(qiáng)類型結(jié)果!
Based on SQLite.
基于SQLite迈倍。You don’t have to manually construct every query by hand.
您不必手動(dòng)構(gòu)造每個(gè)查詢伤靠。A lot of the heavy lifting is handled by code generation.
許多繁重的工作由代碼生??成處理。SQLite database can be navigated with a wide range of tools available today to check data during development.
可以使用當(dāng)今可用的各種工具來瀏覽SQLite數(shù)據(jù)庫啼染,以在開發(fā)期間檢查數(shù)據(jù)宴合。
缺點(diǎn)?? (Cons ??)
- It can be cumbersome to handle schema updates on the local device.
在本地設(shè)備上處理架構(gòu)更新可能很麻煩。 - Web support is still in preview.
Web支持仍在預(yù)覽中迹鹅。 - It has platform-specific dependencies (not written in pure Dart).
它具有特定于平臺的依賴性(不是用純Dart編寫的)卦洽。
用例 (Use case)
If you still need relational data but want to write as little SQL as possible (if you are used to Entity Framework, for instance), this could be a good fit for you.
如果您仍然需要關(guān)系數(shù)據(jù),但想編寫SQL越少越好(例如斜棚,如果您習(xí)慣使用Entity Framework)阀蒂,那么這可能是您的理想選擇。
NoSQL (NoSQL)
There are quite a few options when it comes to NoSQL databases for Flutter as well. We have the heavy hitters that have been around for a long time like Firebase, as well as the newer solutions like Hive. There are many differences between Hive and Firebase but perhaps the main difference is that one can sync to an online store (Firebase), whereas the other is more adequately suited for storing locally on the device (Hive).
Flutter的NoSQL數(shù)據(jù)庫也有很多選擇弟蚀。 我們擁有像Firebase這樣已經(jīng)存在很長時(shí)間的重量級選手蚤霞,以及像Hive這樣的較新解決方案。 Hive和Firebase之間有許多區(qū)別义钉,但也許主要區(qū)別在于争便,一個(gè)可以同步到在線商店(Firebase),而另一個(gè)更適合于在設(shè)備上本地存儲(Hive)断医。
Firebase —在線NoSQL存儲 (Firebase — online NoSQL storage)
Firebase is a traditional document storage database. You store data in collections that are like tables in a traditional database. These collections store documents. Documents store data types, like string
, int
, etc. They can also store a link to another document, so even though Firebase isn't strictly relational you can still create relationships between your data.
Firebase是傳統(tǒng)的文檔存儲數(shù)據(jù)庫滞乙。 您將數(shù)據(jù)存儲在類似于傳統(tǒng)數(shù)據(jù)庫中表的集合中。 這些集合存儲文檔 鉴嗤。 文檔存儲數(shù)據(jù)類型斩启,例如string
, int
等醉锅。它們還可以存儲指向另一個(gè)文檔的鏈接兔簇,因此,即使Firebase不是嚴(yán)格關(guān)系的硬耍,您仍然可以在數(shù)據(jù)之間創(chuàng)建關(guān)系垄琐。
The setup for Firebase is quite involved compared to other on-device options, like Moor or Hive, but you get synchronisation of data between clients and the server. This means that if you have multiple clients with an app and they are all interacting with the same data, then this data can be kept in sync between these clients. Also, this setup is covered quite well in a Google Codelab here. The only downside of this approach is that you don’t get strongly typed data in the same way as you do with Moor or Hive. You have to handle this yourself.
與其他設(shè)備上選項(xiàng)(例如Moor或Hive)相比,F(xiàn)irebase的設(shè)置相當(dāng)復(fù)雜经柴,但是您可以在客戶端和服務(wù)器之間實(shí)現(xiàn)數(shù)據(jù)同步 狸窘。 這意味著,如果您有一個(gè)應(yīng)用程序有多個(gè)客戶端坯认,并且它們都與同一數(shù)據(jù)進(jìn)行交互翻擒,則可以使這些客戶端之間的數(shù)據(jù)保持同步氓涣。 另外, 此處的Google Codelab很好地介紹了此設(shè)置陋气。 這種方法的唯一缺點(diǎn)是劳吠,您不會(huì)像使用Moor或Hive那樣獲得強(qiáng)類型數(shù)據(jù)。 您必須自己處理巩趁。
優(yōu)點(diǎn)?? (Pros ??)
- Synchronises with Firebase online in a near real-time fashion.
以近乎實(shí)時(shí)的方式與Firebase在線同步痒玩。 - Great tooling support.
強(qiáng)大的工具支持。 - Easy to browse data online via the Firebase Console.
通過Firebase控制臺輕松在線瀏覽數(shù)據(jù)议慰。
缺點(diǎn)?? (Cons ??)
- Firebase setup can be complicated if you don’t already have it added to your app.
如果您尚未將Firebase安裝添加到應(yīng)用程序中凰荚,則可能會(huì)很復(fù)雜。 - As the database is online, you need to be mindful of a lot more than a strictly on-device database (like access permissions, for instance).
由于數(shù)據(jù)庫在線褒脯,因此您需要注意的不僅僅是嚴(yán)格的設(shè)備數(shù)據(jù)庫(例如,訪問權(quán)限)缆毁。 - Firebase support for Flutter isn’t in a production ready state just yet.
對Flutter的Firebase支持尚未處于生產(chǎn)就緒狀態(tài)番川。
用例 (Use Case)
If your data is to be spread between many devices and you want (relatively) painless synchronisation between these devices, this could be a good solution for you.
如果您的數(shù)據(jù)要分散在許多設(shè)備之間,并且您想要(相對)在這些設(shè)備之間進(jìn)行輕松的同步脊框,那么這可能是一個(gè)很好的解決方案颁督。
Hive-離線NoSQL存儲 (Hive — offline NoSQL storage)
Hive is an extremely fast NoSQL storage option for Flutter developers. Its biggest selling point is that it is completely native to Dart. This means that anywhere Dart goes, Hive can go, as it doesn’t require any device-specific implementations.
對于Flutter開發(fā)人員來說,Hive是一種非辰奖ⅲ快速的 NoSQL存儲選項(xiàng)沉御。 它最大的賣點(diǎn)是它完全是Dart 原生的 。 這意味著Dart可以進(jìn)行任何操作 昭灵,Hive可以進(jìn)行吠裆,因?yàn)樗?strong>不需要任何特定于設(shè)備的實(shí)現(xiàn) 。
Hive lets you store data as a HiveObject
, which allows for some relations between objects as well. It stores objects in a box
, but you can generate TypeAdapter
s for them.
Hive允許您將數(shù)據(jù)存儲為HiveObject
烂完,這也允許對象之間存在某些關(guān)系试疙。 它將對象存儲在一個(gè)box
,但是您可以為它們生成TypeAdapter
抠蚣。
Creating a box
is fairly simple:
創(chuàng)建一個(gè)box
很簡單:
var box = await Hive.openBox('testBox');
Reading and writing is just as easy:
讀寫很容易:
import 'package:hive/hive.dart';
void main() async {
var box = await Hive.openBox('testBox');
box.put('name', 'David');
print('Name: ${box.get('name')}');
}
Where Hive really shines is in the ability to generate TypeAdapter
s (read more from the documentation). This brings strong typing to your Boxes, and lets you store your classes, and also lets you reference objects in other Boxes.
Hive真正出眾的地方在于能夠生成TypeAdapter
(從文檔中閱讀更多內(nèi)容 )祝旷。 這為Box提供了強(qiáng)大的輸入功能,并允許您存儲類嘶窄,還可以引用其他Box中的對象怀跛。
The documentation shows how to create a box
based on a class with your own definition, like below.
該文檔顯示了如何根據(jù)具有自己定義的類創(chuàng)建box
,如下所示柄冲。
import 'package:hive/hive.dart';
part 'person.g.dart';
@HiveType()
class Person {
@HiveField(0) String name;
@HiveField(1) int age;
@HiveField(2) List<Person> friends;
}
As we can see here, this class contains a List
of Person
, so Hive can reference a list of objects.
正如我們在這里看到的那樣吻谋,該類包含一個(gè)Person
List
,因此Hive可以引用一個(gè)對象列表现横。
用例 (Use case)
If you are just after a simple database to store data on your device, and don’t want the synchronisation that Firebase offers and if you want something that works anywhere, Hive is for you. It’s the database I use in all my apps.
如果您只是想在一個(gè)簡單的數(shù)據(jù)庫中將數(shù)據(jù)存儲在設(shè)備上滨溉,并且不希望Firebase提供同步功能什湘,并且希望在任何地方都可以使用,則Hive適合您 晦攒。 這是我所有應(yīng)用程序中使用的數(shù)據(jù)庫闽撤。
自己做 (Making your own)
If you’re not smitten with any of the above options, you could roll your own database. You would achieve this through using a library like json_serializable
, and storing the JSON files on the device for the app to access.
如果您不喜歡上面的任何選項(xiàng),則可以滾動(dòng)自己的數(shù)據(jù)庫脯颜。 您可以通過使用json_serializable
類的庫并將JSON文件存儲在設(shè)備上以供應(yīng)用訪問來實(shí)現(xiàn)哟旗。
In my opinion, this would be a little bit like building your own car from scratch. Of course, you can do it, and people have done it, but I’m not sure why you would. Creating a new database means creating a new library with potential bugs and so many new issues to consider and think about. If you have set out to make an app, is creating your own database solution really within the scope of doing that?
我認(rèn)為,這有點(diǎn)像從頭開始建造自己的車栋操。 當(dāng)然闸餐,您可以做到,而且人們已經(jīng)做到了矾芙,但是我不確定為什么會(huì)這樣做舍沙。 創(chuàng)建一個(gè)新數(shù)據(jù)庫意味著創(chuàng)建一個(gè)具有潛在錯(cuò)誤以及許多新問題要考慮和思考的新庫。 如果您打算制作一個(gè)應(yīng)用程序剔宪,那么創(chuàng)建自己的數(shù)據(jù)庫解決方案真的在該范圍內(nèi)嗎拂铡?
Existing solutions like Hive or Moor are already in use by a lot of people, all finding bugs and filing issues on GitHub. This is what gives these libraries quality. Who would find bugs on your brand-new, from scratch database? Because you’re the only person that uses it, only you would. That doesn’t sound very appealing does it? I hope not.
像Hive或Moor這樣的現(xiàn)有解決方案已經(jīng)被很多人使用,他們都在GitHub上發(fā)現(xiàn)錯(cuò)誤并提交問題葱绒。 這就是賦予這些庫質(zhì)量的原因 感帅。 誰會(huì)從頭開始在您的全新數(shù)據(jù)庫中發(fā)現(xiàn)錯(cuò)誤? 因?yàn)槟俏ㄒ皇褂盟娜说氐恚?strong>只有您會(huì)使用 失球。 聽起來不是很吸引人嗎? 我希望不是帮毁。
用例 (Use case)
If you completely distrust all code not written by you, or you have some weird esoteric use case, you would maybe consider making your own. I wouldn’t consider doing this in any app I would make though …
如果您完全不信任您未編寫的所有代碼实苞,或者您有一些怪異而深?yuàn)W的用例,則可以考慮自己制作烈疚。 我不會(huì)考慮在我會(huì)制作的任何應(yīng)用程序中這樣做……
這么多的選擇硬梁! 我應(yīng)該使用哪一個(gè)? (So many options! Which one should I use?)
There’s not an easy way to answer what database is “best” — it depends on your use case. But let me sum it up.
沒有哪種簡單的方法可以回答哪個(gè)數(shù)據(jù)庫是“最佳”數(shù)據(jù)庫胞得,這取決于您的使用場景荧止。 但讓我總結(jié)一下。
-
If your data is relational and you want to be able to view it on your computer easily during development — and you don’t mind not having web support — you should use moor.
如果您的數(shù)據(jù)是關(guān)系型的阶剑,并且希望在開發(fā)過程中可以輕松地在計(jì)算機(jī)上查看它-并且您不介意沒有Web支持跃巡,則應(yīng)該使用moor 。
-
If you need your data synchronized between devices and you don’t mind the fairly extended setup, you should use Firebase.
如果您需要在設(shè)備之間同步數(shù)據(jù)并且不介意擴(kuò)展設(shè)置牧愁, 則應(yīng)使用Firebase 素邪。
-
If you want to be up and running really quickly and want great support for the web plus anything else Dart runs on, you should use Hive.
如果您想快速啟動(dòng)并運(yùn)行,并且希望獲得對Web的大力支持以及Dart運(yùn)行的其他功能猪半,則應(yīng)該使用Hive 兔朦。
-
If you have crippling doubt about the security of these databases and nobody can convince you otherwise, and you have a lot of time on your hands, you could consider making your own database or object store with JSON objects. But I wouldn’t.
如果您對這些數(shù)據(jù)庫的安全性有嚴(yán)重的懷疑 偷线,并且沒有人可以說服您,并且您有很多時(shí)間可用沽甥,則可以考慮使用JSON對象創(chuàng)建自己的數(shù)據(jù)庫或?qū)ο蟠鎯Α?但是我不會(huì)声邦。
If I was making an app today, I would probably use Hive.
如果我今天要開發(fā)一個(gè)應(yīng)用程序,那么我可能會(huì)使用Hive 摆舟。
Thanks for reading this article on databases for Flutter. I hope it has made choosing one a little easier for you!
感謝您閱讀有關(guān)Flutter數(shù)據(jù)庫的文章亥曹。 我希望它使您更輕松地選擇一個(gè)!
Is there another Flutter topic that you would just love to know more about? Let me know in the comments! ??
是否有其他Flutter話題恨诱,你想要有更多的了解媳瞪? 在評論中讓我知道! ??
https://www.twitter.com/FlutterComm
https://www.twitter.com/FlutterComm
翻譯自: https://medium.com/flutter-community/choosing-the-right-database-for-your-flutter-app-39ea07e7f6e6
flutter 數(shù)據(jù)庫
轉(zhuǎn)載自weixin_26638123的博客