1. 程式人生 > >擁抱Firebase,Firebase之Realtime Database。(含github原始碼),歡迎關注。

擁抱Firebase,Firebase之Realtime Database。(含github原始碼),歡迎關注。

 1 

R

 I

•COMIC•

D

  3

5

   O 

Firebase可以幫助您構建更出色的移動應用並擴充套件您的業務。 如何工作?

Firebase Realtime Database 允許直接從客戶端程式碼中直接安全訪問資料庫,因此您能夠構建豐富的協作式應用。 資料保留在本地,即使處於離線狀態,實時事件仍繼續觸發,給終端使用者提供一種響應式體驗。當裝置重新取得連線時, Realtime Database 會將本地資料變化與客戶端離線期間發生的遠端更新同步,自動合併任何不一致資料。

實現步驟
  1. 整合 Firebase Realtime Database SDK。

    通過 Gradle、CococaPods 或指令碼包含來快速包含客戶端。

  2. 建立 Realtime Database 引用。

    為設定資料或訂閱資料變化,請引用您的 JSON 資料,如"users/user:1234/phone_number"。

  3. 設定資料和偵聽變化。

    使用此引用寫入資料或訂閱變化。

  4. 啟用離線留存。

    允許將資料寫入到裝置的本地磁碟,以便離線時使用。

  5. 保障資料安全。

    使用 Firebase Realtime Database 安全規則保障您的資料安全。

實操一下又何妨
  1. Install the Firebase SDK.

    《將Firebase新增到專案》

    不會做超連結,有知道的告知下,謝謝

  2. Firebase控制檯新增一個自己的專案。

  3. 新增依賴

  4. 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 一樣簡單。與查詢或掃描資料相比,索引的速度更快,效率更高。

    在Android上儲存資料

有四種方法可以將資料寫入 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;
    }

}

要建立一篇博文並同時更新為最新的活動源和釋出使用者的活動源,該部落格應用需使用如下程式碼:

            
           

相關推薦

擁抱FirebaseFirebaseRealtime 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月將在中國各大高校舉辦包含技術講座、信息分享會以及校園宣講會在 內的一系列校園活動。同學們將有機會和摩根士丹利高管以及返

QTQSignalMapper(可以理解為轉發器多個按鈕綁定到一個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條: 保持健康 程式設計之外的愛好 持續學習 正確應對犯錯 不

【疾風知勁草智者必懷仁】此生我將走過;走過這一次便再也無法重來所有力所能及的善行所有充盈於心的善意我將毫不吝惜即刻傾於我將不再拖延再不淡漠只因此生再也無法重來醒掌天下事醉臥美人膝

此生之路,我將走過;走過這一次,便再也無法重來。所有力所能及的善行,所有充盈於心的善意,我將毫不吝惜,即刻傾於。我將不再拖延,再不淡漠,只因此生之路,再也無法重來。醒掌天下事,醉臥美人膝...

技術就是個紙老虎---為則難者亦易矣;不為則易者亦難矣

         所有HTML語言中的標記都是通過不同的CSS選擇器進行控制的。使用者只需要通過選擇器對不同的HTML標籤進行控制,並賦予各種樣式宣告,以實現各種效果。 一、常見的幾種選擇器 1、標記選擇器          一個HTML頁面有很多不同的標記組成,宣告哪些標記

vue與react對比相同處與不同

兩者都為當下主流框架 相同之處在於: 一、使用 Virtual DOM 二、提供了響應式 (Reactive) 和元件化 (Composable) 的檢視元件。 三、將注意力集中保持在核心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。 不同之處: 一、在 Rea