Android
Firebase Realtime DataBase
Sök…
Anmärkningar
Firebase Realtime DataBase-händelsehanterare
Initiera först FirebaseDatabase:
FirebaseDatabase database = FirebaseDatabase.getInstance();
Skriv till din databas:
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!");
Läs från din databas:
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String value = dataSnapshot.getValue(String.class);
Log.d(TAG, "Value is: " + value);
}
@Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
Hämta data om Android-händelser:
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "postComments:onCancelled", databaseError.toException());
Toast.makeText(mContext, "Failed to load comments.",
Toast.LENGTH_SHORT).show();
}
};
ref.addChildEventListener(childEventListener);
Snabbinställning
Slutför installations- och installationsdelen för att ansluta din app till Firebase.
Detta skapar projektet i Firebase.Lägg till beroendet för Firebase Realtime-databas i din
build.gradle
fil påbuild.gradle
:
compile 'com.google.firebase:firebase-database:10.2.1'
- Konfigurera Firebase-databasregler
Nu är du redo att arbeta med Realtime-databasen i Android.
Till exempel skriver du ett Hello World
meddelande till databasen under message
.
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!");
Designa och förstå hur man hämtar data i realtid från Firebase-databasen
Detta exempel antar att du redan har skapat en Firebase Realtime-databas. Om du är en startare, vänligen informera dig själv här om hur du lägger till Firebase till ditt Android-projekt.
Lägg först till beroende av Firebase-databasen till build.gradle- filen på appnivå :
compile 'com.google.firebase:firebase-database:9.4.0'
Låt oss nu skapa en chat-app som lagrar data i Firebase-databasen.
Steg 1: Skapa en klass med namnet Chat
Skapa bara en klass med några grundläggande variabler som krävs för chatten:
public class Chat{
public String name, message;
}
Steg 2: Skapa lite JSON-data
För att skicka / hämta data till / från Firebas-databasen måste du använda JSON. Låt oss anta att vissa chattar redan har lagrats på rotnivån i databasen. Uppgifterna om dessa chattar kan se ut som följer:
[
{
"name":"John Doe",
"message":"My first Message"
},
{
"name":"John Doe",
"message":"Second Message"
},
{
"name":"John Doe",
"message":"Third Message"
}
]
Steg 3: Lägg till lyssnarna
Det finns tre typer av lyssnare. I följande exempel kommer vi att använda childEventListener
:
DatabaseReference chatDb = FirebaseDatabase.getInstance().getReference() // Referencing the root of the database.
.child("chats"); // Referencing the "chats" node under the root.
chatDb.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// This function is called for every child id chat in this case, so using the above
// example, this function is going to be called 3 times.
// Retrieving the Chat object from this function is simple.
Chat chat; // Create a null chat object.
// Use the getValue function in the dataSnapshot and pass the object's class name to
// which you want to convert and get data. In this case it is Chat.class.
chat = dataSnapshot.getValue(Chat.class);
// Now you can use this chat object and add it into an ArrayList or something like
// that and show it in the recycler view.
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// This function is called when any of the node value is changed, dataSnapshot will
// get the data with the key of the child, so you can swap the new value with the
// old one in the ArrayList or something like that.
// To get the key, use the .getKey() function.
// To get the value, use code similar to the above one.
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
// This function is called when any of the child node is removed. dataSnapshot will
// get the data with the key of the child.
// To get the key, use the s String parameter .
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
// This function is called when any of the child nodes is moved to a different position.
// To get the key, use the s String parameter.
}
@Override
public void onCancelled(DatabaseError databaseError) {
// If anything goes wrong, this function is going to be called.
// You can get the exception by using databaseError.toException();
}
});
Steg 4: Lägg till data i databasen
Skapa bara ett Chat-klassobjekt och lägg till värdena enligt följande:
Chat chat=new Chat();
chat.name="John Doe";
chat.message="First message from android";
Nu får du en referens till chattnoden som gjort i hämtningssessionen:
DatabaseReference chatDb = FirebaseDatabase.getInstance().getReference().child("chats");
Innan du börjar lägga till data, kom ihåg att du behöver ytterligare en djupreferens eftersom en chattnod har flera fler noder och att lägga till en ny chatt betyder att lägga till en ny nod som innehåller chattinformationen. Vi kan generera ett nytt och unikt namn på noden med hjälp av push()
funktionen ( DatabaseReference
objektet), vilket kommer att returnera en annan DatabaseReference
, som i sin tur pekar på en nybildad nod för att infoga chattdata.
Exempel
// The parameter is the chat object that was newly created a few lines above.
chatDb.push().setValue(chat);
Funktionen setValue()
kommer att se till att alla programmets onDataChanged
funktioner kommer att onDataChanged
(inklusive samma enhet), vilket råkar vara den bifogade lyssnaren på "chatt" -noden.
Denormalisering: platt databasstruktur
Denormalisering och en platt databasstruktur är nödvändig för att effektivt ladda ner separata samtal. Med följande struktur är det också möjligt att upprätthålla tvåvägsrelationer. Nackdelen med detta tillvägagångssätt är att du alltid behöver uppdatera data på flera platser.
Tänk dig till exempel en app som låter användaren lagra meddelanden till sig själv (memo).
Önskad platt databasstruktur:
|--database
|-- memos
|-- memokey1
|-- title: "Title"
|-- content: "Message"
|-- memokey2
|-- title: "Important Title"
|-- content: "Important Message"
|-- users
|-- userKey1
|-- name: "John Doe"
|-- memos
|-- memokey1 : true //The values here don't matter, we only need the keys.
|-- memokey2 : true
|-- userKey2
|-- name: "Max Doe"
Den använda memoklassen
public class Memo {
private String title, content;
//getters and setters ...
//toMap() is necessary for the push process
private Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("title", title);
result.put("content", content);
return result;
}
}
Hämtar en användares memos
//We need to store the keys and the memos seperately
private ArrayList<String> mKeys = new ArrayList<>();
private ArrayList<Memo> mMemos = new ArrayList<>();
//The user needs to be logged in to retrieve the uid
String currentUserId = FirebaseAuth.getInstance().getCurrentUser().getUid();
//This is the reference to the list of memos a user has
DatabaseReference currentUserMemoReference = FirebaseDatabase.getInstance().getReference()
.child("users").child(currentUserId).child("memos");
//This is a reference to the list of all memos
DatabaseReference memoReference = FirebaseDatabase.getInstance().getReference()
.child("memos");
//We start to listen to the users memos,
//this will also retrieve the memos initially
currentUserMemoReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//Here we retrieve the key of the memo the user has.
String key = dataSnapshot.getKey(); //for example memokey1
//For later manipulations of the lists, we need to store the key in a list
mKeys.add(key);
//Now that we know which message belongs to the user,
//we request it from our memos:
memoReference.child(key).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Here we retrieve our memo:
Memo memo = dataSnapshot.getValue(Memo.class);
mMemos.add(memo);
}
@Override
public void onCancelled(DatabaseError databaseError) { }
});
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) { }
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) { }
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) { }
@Override
public void onCancelled(DatabaseError databaseError) { }
}
Skapa ett memo
//The user needs to be logged in to retrieve the uid
String currentUserUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
//This is the path to the list of memos a user has
String userMemoPath = "users/" + currentUserUid + "/memos/";
//This is the path to the list of all memos
String memoPath = "memos/";
//We need to retrieve an unused key from the memos reference
DatabaseReference memoReference = FirebaseDatabase.getInstance().getReference().child("memos");
String key = memoReference.push().getKey();
Memo newMemo = new Memo("Important numbers", "1337, 42, 3.14159265359");
Map<String, Object> childUpdates = new HashMap<>();
//The second parameter **here** (the value) does not matter, it's just that the key exists
childUpdates.put(userMemoPath + key, true);
childUpdates.put(memoPath + key, newMemo.toMap());
FirebaseDatabase.getInstance().getReference().updateChildren(childUpdates);
Efter pushen eller databasen ser så här ut:
|--database
|-- memos
|-- memokey1
|-- title: "Title"
|-- content: "Message"
|-- memokey2
|-- title: "Important Title"
|-- content: "Important Message"
|-- generatedMemokey3
|-- title: "Important numbers"
|-- content: "1337, 42, 3.14159265359"
|-- users
|-- userKey1
|-- name: "John Doe"
|-- memos
|-- memokey1 : true //The values here don't matter, we only need the keys.
|-- memokey2 : true
|-- generatedMemokey3 : true
|-- userKey2
|-- name: "Max Doe"
Förstå JSON-databas för brandbas
Innan vi blir smutsiga med händerna känner jag att det är nödvändigt att förstå hur data lagras i eldfasen. Till skillnad från relationella databaser lagrar eldbas data i JSON-format. Tänk på varje rad i en relationsdatabas som ett JSON-objekt (som i princip är oordnat nyckelvärdespar). Så kolumnnamnet blir nyckel och värdet som lagras i den kolumnen för en viss rad är värdet. På så sätt representeras hela raden som ett JSON-objekt och en lista över dessa representerar en hel databastabell. Den omedelbara fördelen som jag ser för detta är schemamodifiering blir mycket billigare operation jämfört med gamla RDBMS. Det är lättare att lägga till ett par fler attribut till en JSON än att ändra en tabellstruktur.
här är ett exempel på JSON för att visa hur data lagras i eldfasen:
{
"user_base" : {
"342343" : {
"email" : "[email protected]",
"authToken" : "some string",
"name" : "Kaushal",
"phone" : "+919916xxxxxx",
"serviceProviderId" : "firebase",
"signInServiceType" : "google",
},
"354895" : {
"email" : "[email protected]",
"authToken" : "some string",
"name" : "devil",
"phone" : "+919685xxxxxx",
"serviceProviderId" : "firebase",
"signInServiceType" : "github"
},
"371298" : {
"email" : "[email protected]",
"authToken" : "I am batman",
"name" : "Bruce Wayne",
"phone" : "+14085xxxxxx",
"serviceProviderId" : "firebase",
"signInServiceType" : "shield"
}
},
"user_prefs": {
"key1":{
"data": "for key one"
},
"key2":{
"data": "for key two"
},
"key3":{
"data": "for key three"
}
},
//other structures
}
Detta visar tydligt hur data som vi brukade lagra i relationsdatabaser kan lagras i JSON-format. Låt oss därefter se hur du läser denna information i Android-enheter.
Hämtar data från brandbasen
Jag antar att du redan vet om att lägga till bränslebaserad beroende i Android-studio. Om du inte bara följer guiden härifrån . Lägg till din app i brandbaskonsolen, gradle sync android studio efter att ha lagt till beroenden. Alla beroenden behövs inte bara brandbasdatabas och brandbasautorisation.
Nu när vi vet hur data lagras och hur man lägger till gradberoende beror på hur vi använder den importerade eldbasen android SDK för att hämta data.
skapa en brandbasdatabasreferens
DatabaseReference userDBRef = FirebaseDatabase.getInstance().getReference();
// above statement point to base tree
userDBRef = DatabaseReference.getInstance().getReference().child("user_base")
// points to user_base table JSON (see previous section)
härifrån kan du kedja flera barn () -metodsamtal för att peka på de data du är intresserad av. Till exempel om data lagras som visas i föregående avsnitt och du vill peka på Bruce Wayne-användare kan du använda:
DatabaseReference bruceWayneRef = userDBRef.child("371298");
// 371298 is key of bruce wayne user in JSON structure (previous section)
Eller bara skicka hela referensen till JSON-objektet:
DatabaseReference bruceWayneRef = DatabaseReference.getInstance().getReference()
.child("user_base/371298");
// deeply nested data can also be referenced this way, just put the fully
// qualified path in pattern shown in above code "blah/blah1/blah1-2/blah1-2-3..."
Nu när vi har referensen till de data vi vill hämta kan vi använda lyssnare för att hämta data i Android-appar. Till skillnad från de traditionella samtal där du avfyrar REST API-samtal med eftermontering eller volley krävs här en enkel återuppringningslyssnare för att få informationen. Firebase sdk kallar återuppringningsmetoderna och du är klar.
Det finns i princip två typer av lyssnare som du kan ansluta, den ena är ValueEventListener och den andra är ChildEventListener (beskrivs i nästa avsnitt). För alla förändringar i data under noden har vi referenser och lagt till lyssnare till, värdhändelsens lyssnare returnerar hela JSON-strukturen och barnhändelsens lyssnare returnerar ett specifikt barn där förändringen har skett. Båda dessa är användbara på sitt eget sätt. För att hämta uppgifterna från brandbasen kan vi lägga till en eller flera lyssnare till en referens för brandbasdatabas (lista userDBRef som vi skapade tidigare).
Här är några exempelkoder (kodförklaring efter kod):
userDBRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User bruceWayne = dataSnapshot.child("371298").getValue(User.class);
// Do something with the retrieved data or Bruce Wayne
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e("UserListActivity", "Error occured");
// Do something about the error
});
Visste du att klasstypen passerade. DataSnapshot kan konvertera JSON-data till våra definierade POJO: er, enkelt passera rätt klasstyp.
Om ditt användningsfall inte kräver hela data (i vårt fall user_base-tabell) varje gång en liten förändring inträffar eller säger att du bara vill hämta data en gång , kan du använda addListenerForSingleValueEvent () -metoden för databasreferens. Detta avbryter återuppringningen bara en gång.
userDBRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Do something
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Do something about the error
});
Ovanstående prover ger dig värdet på JSON-noden. För att få nyckeln, ring bara:
String myKey = dataSnapshot.getKey();
Lyssna på uppdateringar av barn
Ta ett användningsfall, som en chatt-app eller en samarbetshandelslista-app (som i princip kräver en lista över objekt som ska synkroniseras mellan användare). Om du använder firebasdatabas och lägger till en värdhändelselister till chattens överordnade nod eller livsmedelslistans föräldernod, kommer du att avsluta med hela chattstrukturen från början av tiden (jag menade början av din chatt) varje gång en chattnod läggs till ( dvs någon säger hej). Att vi inte vill göra, det vi är intresserade av är bara den nya noden eller bara den gamla noden som har tagits bort eller ändrats, de oförändrade bör inte returneras.
I det här fallet kan vi använda ChildEvenListener . Utan ytterligare adieu, här är kodprov (se föregående avsnitt för prov JSON-data):
userDBRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
//If not dealing with ordered data forget about this
}
@Override
public void onCancelled(DatabaseError databaseError) {
});
Metodnamn är självförklarande. Som du kan se när en ny användare läggs till eller någon egendom hos befintlig användare ändras eller användaren raderas eller tas bort lämplig återuppringningsmetod för barndagshändaren kallas med relevant data. Så om du håller UI uppdaterat för chatt-appen, kan du skaffa JSON från onChildAdded () i POJO och anpassa den till din UI. Kom bara ihåg att ta bort din lyssnare när användaren lämnar skärmen.
onChildChanged () ger hela barnet värde med ändrade egenskaper (nya).
onChiledRemoved () returnerar den borttagna barnnoden.
Hämtar data med pagination
När du har en enorm JSON-databas är det inte meningsfullt att lägga till en lyssnar på ett händelsevärde. Det kommer att returnera den enorma JSON och att analysera det skulle vara tidskrävande. I sådana fall kan vi använda pagination och hämta en del av data och visa eller bearbeta den. Typ av som lat laddning eller som att hämta gamla chattar när användaren klickar på visa äldre chatt. I det här fallet Query kan användas.
Låt oss ta vårt gamla exempel i tidigare avsnitt. Användarbasen innehåller 3 användare om den växer till att säga 3 hundra tusen användare och du vill hämta användarlistan i partier om 50:
// class level
final int limit = 50;
int start = 0;
// event level
Query userListQuery = userDBRef.orderByChild("email").limitToFirst(limit)
.startAt(start)
userListQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Do something
start += (limit+1);
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Do something about the error
});
Här kan värden eller barnhändelser läggas till och lyssnas på. Ring frågan igen för att hämta nästa 50. Se till att lägga till orderByChild () -metoden , detta fungerar inte utan det. Firebase måste veta i vilken ordning du paginerar.