擁抱Firebase,Firebase之Realtime Database。(含github原始碼),歡迎關注。
1
T
R
E I
•COMIC•
D
3
5
O
Firebase可以幫助您構建更出色的移動應用並擴充套件您的業務。 如何工作?
Firebase Realtime Database 允許直接從客戶端程式碼中直接安全訪問資料庫,因此您能夠構建豐富的協作式應用。 資料保留在本地,即使處於離線狀態,實時事件仍繼續觸發,給終端使用者提供一種響應式體驗。當裝置重新取得連線時, Realtime Database 會將本地資料變化與客戶端離線期間發生的遠端更新同步,自動合併任何不一致資料。
-
整合 Firebase Realtime Database SDK。
通過 Gradle、CococaPods 或指令碼包含來快速包含客戶端。
-
建立 Realtime Database 引用。
為設定資料或訂閱資料變化,請引用您的 JSON 資料,如"users/user:1234/phone_number"。
-
設定資料和偵聽變化。
使用此引用寫入資料或訂閱變化。
-
啟用離線留存。
允許將資料寫入到裝置的本地磁碟,以便離線時使用。
-
保障資料安全。
使用 Firebase Realtime Database 安全規則保障您的資料安全。
-
Install the Firebase SDK.
見《將Firebase新增到專案》
不會做超連結,有知道的告知下,謝謝
-
在Firebase控制檯新增一個自己的專案。
-
新增依賴
-
compile 'com.google.firebase:firebase-database:10.2.6'
4. 配置Firebase Database規則
預設情況下,您的資料庫規則會授予完全讀取和寫入許可權,但僅授予給已通過身份驗證的使用者。 以下為預設規則:
{"rules":{".read":"auth != null",".write":"auth != null"}}
如果您只是剛開始使用並希望在配置安全規則之前先試用資料庫,則可使用以下規則授予完全的公共資料庫訪問許可權:
{"rules":{".read":true,".write":true}}
在釋出您的應用之前必須正確配置這些規則,以確保您的使用者只能訪問他們應該能夠訪問的資料。
如何使用安全規則保障資料安全
程式碼混淆# Add this global rule組織您的資料庫
-keepattributes Signature# This rule will properly ProGuard all the model classes in# the package com.yourcompany.models. Modify to fit the structure# of your app.
-keepclassmembers class com.yourcompany.models.** {
*;
}
構建一個結構合理的資料庫需要預先進行大量計劃。最重要的是,您需要對如何儲存資料及之後如何檢索資料做好計劃,儘可能簡化儲存和檢索的程序。
所有 Firebase Realtime Database 資料都被儲存為 JSON 物件。您可將該資料庫視為雲託管 JSON 樹。 該資料庫與 SQL 資料庫不同,沒有任何表格或記錄。 當您將資料新增至 JSON 樹時,它變為現有 JSON 結構中的一個節點。
例如,假設聊天應用允許使用者儲存基本個人資料和聯絡人列表。 通常使用者個人資料位於一個諸如 /users/$uid
之類的路徑中。
使用者 alovelace
的資料庫項看起來可能如下所示:
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
"contacts": { "ghopper": true },
},
"ghopper": { ... },
"eclarke": { ... }
}
}
資料結構最佳做法
-
避免巢狀資料
Firebase Realtime Database 允許巢狀資料的深度多達 32 層,但是官網文件卻不建議巢狀,因為要提取資料庫中某個資料時,要檢索所有的子節點,另外,當向某使用者授予資料庫中某個節點的讀寫訪問權時,也會將該節點下所有資料的訪問權授予該使用者。
假設一個如下所示的多層巢狀結構:
{
// This is a poorly nested data architecture, because iterating the children// of the "chats" node to get a list of conversation titles requires// potentially downloading hundreds of megabytes of messages"chats": {
"one": {
"title": "Historical Tech Pioneers",
"messages": {
"m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
"m2": { ... },
// a very long list of messages
}
},
"two": { ... }
}
}
若採用這種巢狀設計,迴圈訪問資料就會出現問題。例如,要列出聊天對話標題,就需要將整個 chats
樹(包括所有成員和訊息)都下載到客戶端。
-
平展資料結構
如果資料被拆分到不同路徑(又稱反規範化),則可根據需要通過不同調用有效地下載。 請考慮此平面化結構:
{
// Chats contains only meta info about each conversation// stored under the chats's unique ID"chats": {
"one": {
"title": "Historical Tech Pioneers",
"lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
"timestamp": 1459361875666
},
"two": { ... },
"three": { ... }
},
// Conversation members are easily accessible// and stored by chat conversation ID"members": {
// we'll talk about indices like this below"one": {
"ghopper": true,
"alovelace": true,
"eclarke": true
},
"two": { ... },
"three": { ... }
},
// Messages are separate from data we may want to iterate quickly// but still easily paginated and queried, and organized by chat// converation ID"messages": {
"one": {
"m1": {
"name": "eclarke",
"message": "The relay seems to be malfunctioning.",
"timestamp": 1459361875337
},
"m2": { ... },
"m3": { ... }
},
"two": { ... },
"three": { ... }
}
}
現在,每個對話只需下載幾個位元組即可迴圈訪問房間列表,同時可以快速提取元資料,在 UI 中列出或顯示房間。
在訊息到達時,可單獨提取和顯示,從而確保 UI 的及時響應和速度。
-
建立可擴充套件的資料
假設使用者與群組之間存在雙向關係。 使用者可屬於一個群組,且群組包含一個使用者列表。 當需要決定使用者屬於哪些群組時,情況就會比較複雜。
我們需要的是一種完善方法,不僅列出使用者所屬群組,而且只提取這些群組的資料。 對群組的"索引"在此可能有很大的幫助:
// An index to track Ada's memberships
{
"users": {
"alovelace": {
"name": "Ada Lovelace",
// Index Ada's groups in her profile"groups": {
// the value here doesn't matter, just that the key exists"techpioneers": true,
"womentechmakers": true
}
},
...
},
"groups": {
"techpioneers": {
"name": "Historical Tech Pioneers",
"members": {
"alovelace": true,
"ghopper": true,
"eclarke": true
}
},
...
}
}
這種索引是通過儲存 Ada 記錄及該群組下的關係來重複某些資料的。 現在,alovelace
在一個群組下進行索引,而 techpioneers
則列在
Ada 的個人資料中。 所以要從該群組刪除 Ada,則必須在兩個地方更新。
對於雙向關係而言,這是必要的冗餘。這樣,您就可以快速、高效地提取 Ada 的成員身份,而且即使使用者或群組列表有數百萬條記錄,或 Realtime Database 安全規則會阻止訪問某些記錄,也不受影響。
這種方法通過將 ID 列為金鑰並將值設為 true 來顛倒資料,使金鑰檢查變得像讀取 /users/$uid/groups/$group_id
和檢查是否 null
一樣簡單。與查詢或掃描資料相比,索引的速度更快,效率更高。
有四種方法可以將資料寫入 Firebase Realtime Database:
setValue():
常見用法:將資料寫入或替換到定義的路徑,如 users/<user-id>/<username>
。
push():
常見用法: 新增到資料列表。每次呼叫 push()
時,Firebase
均會生成唯一 ID,如 user-posts/<user-id>/<unique-post-id>
。
updateChildren():
常見用法:更新定義的路徑中的部分鍵,而不替換所有資料。
runTransaction():
常見用法:更新可能因併發更新而損壞的複雜資料。
寫入、更新或刪除引用中的資料
基本寫入操作
對於基本寫入操作,您可以使用 setValue()
將資料儲存至特定引用,替換該路徑的任何現有資料。
可以使用該方法執行下列操作:
-
傳遞與可用 JSON 型別對應的型別,如下所示:
-
String
-
Long
-
Double
-
Boolean
-
Map<String, Object>
-
List<Object>
-
-
傳遞自定義 Java 物件(如果定義該物件的類的預設建構函式不接受引數,且為要指定的屬性提供了公用 getter)。 如果使用 Java 物件,則物件的內容將自動以巢狀方式對映到子位置。使用 Java 物件通常還會提高程式碼的可讀性,使其更易於維護。例如,如果應用包含使用者的基本個人資料,則
User
物件可能如下所示:
@IgnoreExtraPropertiespublicclassUser {
publicString username;
publicString email;
publicUser() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
publicUser(String username, String email) {
this.username = username;
this.email = email;
}
}
可以使用 setValue()
新增使用者,如下所示:
privatevoid writeNewUser(String userId, String name, String email) {
User user = newUser(name, email);
mDatabase.child("users").child(userId).setValue(user);
}
以這種方式使用 setValue()
將覆蓋指定位置的資料,包括所有子節點。但是,您仍可在不重寫整個物件的情況下更新子節點。 如果要允許使用者更新其個人資料,則可按照如下所示更新使用者名稱:
mDatabase.child("users").child(userId).child("username").setValue(name);
追加到資料列表
使用 push()
方法可將資料追加到多使用者應用中的列表。每次將新子節點新增到指定的
Firebase 引用時,push()
方法均會生成唯一
ID。
通過為列表中的各新元素使用自動生成的鍵,多個客戶端可以同時向同一位置新增子節點,而不存在寫入衝突。
push()
生成的唯一 ID 基於時間戳,因此列表專案會自動按時間順序排列。
您可以使用對新資料(由 push()
方法返回)的引用獲取子節點自動生成的鍵的值或為子節點設定資料。
對 push()
引用呼叫 getKey()
將返回自動生成的鍵值。
更新特定欄位
要同時向一個節點的特定子節點寫入資料,而不覆蓋其他子節點,請使用 updateChildren()
方法。
呼叫 updateChildren()
時,可以通過為鍵指定路徑來更新較低級別的子值。
例如,社交部落格應用可能具有 Post
類,如下所示:
@IgnoreExtraPropertiespublicclassPost {
publicString uid;
publicString author;
publicString title;
publicString body;
publicint starCount = 0;
publicMap<String, Boolean> stars = newHashMap<>();
publicPost() {
// Default constructor required for calls to DataSnapshot.getValue(Post.class)
}
publicPost(String uid, String author, String title, String body) {
this.uid = uid;
this.author = author;
this.title = title;
this.body = body;
}
@ExcludepublicMap<String, Object> toMap() {
HashMap<String, Object> result = newHashMap<>();
result.put("uid", uid);
result.put("author", author);
result.put("title", title);
result.put("body", body);
result.put("starCount", starCount);
result.put("stars", stars);
return result;
}
}
要建立一篇博文並同時更新為最新的活動源和釋出使用者的活動源,該部落格應用需使用如下程式碼:
相關推薦
擁抱Firebase,Firebase之Realtime Database。(含github原始碼),歡迎關注。
1 T R E I •COMIC• D 3 5 O Firebase可以幫助您構建更出色的移動應用並擴充套件您的業務。 如何工作? Firebase Realti
開發訊息推送服務,基於Netty protobuf--fpush(含github原始碼)
開發訊息推送服務,基於Netty protobuf--fpush-含github原始碼 技術棧 程式碼簡介 系統架構 1.系統部署架構圖如下: 2. 移動客戶端鑑定許可權原理 3. server端推送
練習 1-3 修改溫度轉換程式,使之能在轉換表的頂部列印一個標題。
C語言程式設計(第二版) 練習1-3 個人設計 練習1-3 修改溫度轉換程式,使之能在轉換表的頂部列印一個標題。 程式碼塊: #include <stdio.h> #include <stdlib.h> int main() { double c,
點擊頁面的按鈕,使之打開一個新窗口,加載一個頁面的方法有哪些呢?
body del .html blank oca pos type target put 1.<base target="_blank" /> 頁面只要有a標簽,都會打開一個新的頁面; 2.<input type=‘button‘ value=‘new‘
原來C++之父在大摩工作呀,並且還是總經理。。
trac rac 進行 原來 其它 包含 大牛 mod post 摩根士丹利信息技術部門簡歷接收即將截止。請同學們抓緊投遞 摩根士丹利9月、10月將在中國各大高校舉辦包含技術講座、信息分享會以及校園宣講會在 內的一系列校園活動。同學們將有機會和摩根士丹利高管以及返
QT之QSignalMapper(可以理解為轉發器,多個按鈕綁定到一個Edit上,且能分辨。每個單獨連接的話,反而麻煩)
this 不同的 lan each b2c etc gpo 知識點 span QT之QSignalMapper QT之QSignalMapper 簡述 效果圖 上代碼 相關知識點文章 結尾 簡述 QSign
這是一套Java菜鳥到大牛的學習路線之高級教程,由工作了10年的資深Java架構師整理。
script gin 視頻 提速 entos 分布式存 內幕 服務 www 這是一套Java菜鳥到大牛的學習路線之高級教程,由工作了10年的資深Java架構師整理。 01-java高級架構師設計-基礎深入 J
[Windows10]記一次修復註冊表相關血案:該文件沒有與之關聯的應用來執行該操作。請安裝應用,若已經安裝應用,請在“默認應用設置”頁面中創建關聯。
src 相關 overflow 還在 一次 註冊表 forum sin 嘗試 今天閑得蛋疼清理了一下右鍵菜單,於是在之後某時刻使用Everything的“雙擊路徑列打開目錄”功能時發現異常: [Window Title] Everything
《SpringBoot從入門到放棄》之第(十)篇——整合Redis(SpringBoot 2.0 版本),寫於2018年10月24號程式設計師節。
在 pom.xml 配置中新增 jar 依賴: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-d
ES6學習路上的小學生,promise處理非同步操作,簡易原始起步之用。先能用,再深究!
ES6的promise物件,讓我們更容易的處理這樣的需求:執行完一個方法以後,再去執行下一個方法。 理解尚淺之時,先用於專案之中。 1 var promise1 = new Promise(function(resolve, reject) { 2 //
ES6學習路上的小學生,promise處理異步操作,簡易原始起步之用。先能用,再深究!
接收 class 異步操作 簡單的 小學生 resolv ces 後置 小學 ES6的promise對象,讓我們更容易的處理這樣的需求:執行完一個方法以後,再去執行下一個方法。 理解尚淺之時,先用於項目之中。 1 var promise1 = new P
前端之路:網頁內容轉圖片,並且複製網頁內容,並且優化體驗。(截圖外掛Clipboard.js 的使用)。
做專案遇到一個比較奇葩的需求,覺得很有意思,記錄下。方便以後回憶。 涉及框架(html2canvas.min.js clipboard.mn.js): 直接連cdn <script src="https://cdn.bootcss.com/jquery/3.3
《程式設計珠璣》程式碼之路9:請粗略估計,200萬一個值和一個指標的結構體能否存入128MB記憶體。
這個問題是《程式設計珠璣》第七章的一個問題。主要就是說像一個結構體中包含一個int和一個char,加起來是5個位元組,但因為位元組對齊的需要,實際會佔用8位元組。就這麼多麼? 作為經典鉅著,當然不會這麼一點點啦。 看下圖: 這幅圖是告訴我們,一個對齊後sizeof()列大小的結構體
合併兩個有序連結串列,合併之後任然是有序的並輸出。
合併連結串列相信大家都特別熟悉,但是如果要加上一定的輸出格式,難度就會有所增加,不說了,見程式碼。 #include<iostream> using namespace std; struct Node{ Node *next; int data
從業程式設計生涯十年,你要了解的程式設計師養生之道,以及進階之路。
作為一個從業快10年的程式設計師,我想給新入行的程式設計師們一些建議。這些建議是我希望自己可以在畢業時就讀到的,也希望它們可以幫助你成為一個更好的程式設計師。文末有資料分享。 簡單歸納一下,總共有7條: 保持健康 程式設計之外的愛好 持續學習 正確應對犯錯 不
定義一個複數類Complex,過載運算子“+”,“-”,“*”,“/”,使之能用於複數的加、減、乘、除。運算子過載函式作為Complex類的成員函式。編寫程式,分別求兩個複數之和、差、積和商。
#include <iostream> #include <iomanip> using namespace std; class Complex { public: Complex(); Complex(double r
定義一個複數類Complex,過載運算子“+”,使之能用於複數的加法運算。參加運算的兩個運算量可以都是類物件,也可以其中有一個是整數,順序任意。例如,c1+c2,i+c1,c1+i均合法(設i為整數,
#include <iostream> #include <iomanip> using namespace std; class Complex { public: Complex() { real=0;
【疾風知勁草,智者必懷仁】此生之路,我將走過;走過這一次,便再也無法重來。所有力所能及的善行,所有充盈於心的善意,我將毫不吝惜,即刻傾於。我將不再拖延,再不淡漠,只因此生之路,再也無法重來。醒掌天下事,醉臥美人膝
此生之路,我將走過;走過這一次,便再也無法重來。所有力所能及的善行,所有充盈於心的善意,我將毫不吝惜,即刻傾於。我將不再拖延,再不淡漠,只因此生之路,再也無法重來。醒掌天下事,醉臥美人膝...
技術就是個紙老虎---為之,則難者亦易矣;不為,則易者亦難矣。
所有HTML語言中的標記都是通過不同的CSS選擇器進行控制的。使用者只需要通過選擇器對不同的HTML標籤進行控制,並賦予各種樣式宣告,以實現各種效果。 一、常見的幾種選擇器 1、標記選擇器 一個HTML頁面有很多不同的標記組成,宣告哪些標記
vue與react對比,相同之處與不同之處。
兩者都為當下主流框架 相同之處在於: 一、使用 Virtual DOM 二、提供了響應式 (Reactive) 和元件化 (Composable) 的檢視元件。 三、將注意力集中保持在核心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。 不同之處: 一、在 Rea