Поиск…


замечания

Другие связанные темы:

Firebase Realtime DataBase обработчик событий

Первая инициализация FirebaseDatabase:

FirebaseDatabase database = FirebaseDatabase.getInstance();

Напишите в базу данных:

// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");

myRef.setValue("Hello, World!");

Читайте в базе данных:

// 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());
    }
});

Получить данные о событиях Android:

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);

Быстрая установка

  1. Заполните раздел « Установка и настройка», чтобы подключить ваше приложение к Firebase.
    Это создаст проект в Firebase.

  2. Добавьте зависимость для базы данных Firebase Realtime к вашему файлу build.gradle уровне build.gradle :

compile 'com.google.firebase:firebase-database:10.2.1'
  1. Настройка правил базы данных Firebase

Теперь вы готовы работать с базой данных Realtime в Android.

Например, вы пишете сообщение Hello World в базу данных под ключом message .

// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");

myRef.setValue("Hello, World!");

Проектирование и понимание того, как извлекать данные в реальном времени из базы данных Firebase

В этом примере предполагается, что вы уже создали базу данных Firebase Realtime. Если вы начинаете, пожалуйста, сообщите здесь, как добавить Firebase в свой проект Android.

Во-первых, добавьте зависимость базы данных Firebase к файлу build.gradle на уровне приложения :

compile 'com.google.firebase:firebase-database:9.4.0'

Теперь давайте создадим чат-приложение, которое хранит данные в базе данных Firebase.

Шаг 1. Создайте класс с именем Чат

Просто создайте класс с некоторыми основными переменными, необходимыми для чата:

public class Chat{
    public String name, message;
}

Шаг 2: Создайте некоторые данные JSON

Для отправки / получения данных в / из базы данных Firebase вам необходимо использовать JSON. Предположим, что некоторые чаты уже хранятся на корневом уровне в базе данных. Данные этих чатов могут выглядеть следующим образом:

[
    {
        "name":"John Doe",
        "message":"My first Message"
    },
    {
        "name":"John Doe",
        "message":"Second Message"
    },
    {
        "name":"John Doe",
        "message":"Third Message"
    }
]

Шаг 3: Добавление слушателей

Существует три типа слушателей. В следующем примере мы будем использовать 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();
    }
});

Шаг 4: добавление данных в базу данных

Просто создайте объект класса Chat и добавьте значения следующим образом:

Chat chat=new Chat();
chat.name="John Doe";
chat.message="First message from android";

Теперь получите ссылку на узел чатов, как это сделано в сеансе извлечения:

DatabaseReference chatDb = FirebaseDatabase.getInstance().getReference().child("chats");

Прежде чем приступать к добавлению данных, имейте в виду, что вам нужна еще одна глубокая ссылка, поскольку узел чата имеет еще несколько узлов и добавление нового чата означает добавление нового узла, содержащего детали чата. Мы можем сгенерировать новое и уникальное имя узла, используя функцию push() объекта DatabaseReference , которая вернет другой DatabaseReference , который, в свою очередь, указывает на вновь образованный узел, чтобы вставить данные чата.

пример

// The parameter is the chat object that was newly created a few lines above.
chatDb.push().setValue(chat);

Функция setValue() будет обеспечивать, чтобы все функции onDataChanged приложения onDataChanged (включая одно и то же устройство), что является приложенным слушателем узла «чаты».

Денормализация: плоская структура базы данных

Денормализация и плоская структура базы данных необходимы для эффективной загрузки отдельных вызовов. Со следующей структурой также можно поддерживать двусторонние отношения. Недостатком такого подхода является то, что вам всегда нужно обновлять данные в нескольких местах.

Например, представьте приложение, которое позволяет пользователю хранить сообщения для себя (заметки).

Желаемая плоская структура базы данных:

|--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"

Используемый класс memo

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;
    }
}

Получение заметок пользователя

//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) { }
    }

Создание заметки

//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);

После нажатия или базы данных выглядит следующим образом:

|--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"

Понимание базы данных JSON базы Firebase

Прежде чем мы соберём свои руки с кодом, я чувствую, что необходимо понять, как данные хранятся в firebase. В отличие от реляционных баз данных, firebase хранит данные в формате JSON. Подумайте о каждой строке в реляционной базе данных как о объекте JSON (который в основном является неупорядоченной парой ключ-значение). Таким образом, имя столбца становится ключевым, а значение, хранящееся в этом столбце для одной конкретной строки, является значением. Таким образом, вся строка представляется как объект JSON, а список из них представляет собой всю таблицу базы данных. Непосредственная польза, которую я вижу для этого, - это изменение схемы становится намного более дешевой по сравнению со старой РСУБД. Легче добавить еще несколько атрибутов в JSON, чем изменить структуру таблицы.

вот пример JSON, чтобы показать, как данные хранятся в firebase:

   {
    "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
  }

Это ясно показывает, как данные, которые мы использовали для хранения в реляционных базах данных, могут храниться в формате JSON. Затем давайте посмотрим, как читать эти данные в устройствах Android.

Извлечение данных из базы

Я собираюсь предположить, что вы уже знаете о добавлении firebase зависимостей градиента в студии android. Если вы не просто следуете инструкциям отсюда . Добавьте свое приложение в консоль firebase, студию градиента синдрома android после добавления зависимостей. Все зависимости не нужны, просто база данных firebase и firebase auth.

Теперь, когда мы знаем, как хранятся данные и как добавить зависимости gradle, посмотрим, как использовать импортированный SDK для firebase android SDK для извлечения данных.

создать ссылку базы данных firebase

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)

отсюда вы можете связать несколько вызовов метода child (), чтобы указать на интересующие вас данные. Например, если данные хранятся, как показано в предыдущем разделе, и вы хотите указать на пользователя Bruce Wayne, вы можете использовать:

DatabaseReference bruceWayneRef = userDBRef.child("371298");
// 371298 is key of bruce wayne user in JSON structure (previous section)

Или просто передайте всю ссылку на объект JSON:

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..."

Теперь, когда у нас есть ссылка на данные, которые мы хотим получить, мы можем использовать прослушиватели для извлечения данных в приложениях для Android. В отличие от традиционных вызовов, в которых вы запускаете вызовы API REST с использованием модификации или волейбола, здесь необходим простой прослушиватель обратного вызова для получения данных. Firebase sdk вызывает методы обратного вызова, и все готово.

В основном есть два типа слушателей, которые вы можете присоединить, один - ValueEventListener, а другой - ChildEventListener (описан в следующем разделе). Для любого изменения данных в узле у нас есть ссылки и добавлены слушатели, функция event eventers возвращает всю структуру JSON, а прослушиватель дочерних событий возвращает конкретный ребенок, где произошло изменение. Оба они полезны по-своему. Для извлечения данных из firebase мы можем добавить одного или нескольких слушателей в ссылку базы данных firebase (список userDBRef, который мы создали ранее).

Вот пример кода (объяснение кода после кода):

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
    });

Вы заметили, что тип класса прошел. DataSnapshot может преобразовывать данные JSON в наши определенные POJO, просто передать правильный тип класса.

Если ваш прецедент не требует целых данных (в нашем случае user_base table) каждый раз, когда происходит какое-то небольшое изменение или вы хотите получить данные только один раз , вы можете использовать метод addListenerForSingleValueEvent () ссылки базы данных. Это срабатывает только один раз.

userDBRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // Do something
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Do something about the error
    });

Над образцами вы получите значение узла JSON. Чтобы получить ключ, просто позвоните:

String myKey = dataSnapshot.getKey();

Прослушивание обновлений для детей

Возьмите пример использования, например, приложение чата или приложение для совместного использования продуктов (для которого в основном требуется список объектов для синхронизации между пользователями). Если вы используете базу данных firebase и добавляете прослушиватель событий значения к родительскому узлу чата или родительскому узлу списка продуктов, вы будете заканчивать всю структуру чата с самого начала (я имел в виду начало вашего чата) каждый раз, когда добавляется узел чата ( т.е. кто-то говорит привет). То, что мы не хотим делать, нас интересует только новый узел или только старый узел, который был удален или изменен, неизменные не должны возвращаться.

В этом случае мы можем использовать ChildEvenListener . Без дальнейшего рассмотрения, вот пример кода (см. Предыдущие разделы для образцов данных JSON):

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) {
    });

Имя метода самоочевидно. Как вы можете видеть, когда новый пользователь добавлен или какое-либо свойство существующего пользователя модифицировано, или пользователь удален или удален, соответствующий метод обратного вызова дочернего прослушивателя событий вызывается с соответствующими данными. Поэтому, если вы сохраняете обновленный пользовательский интерфейс для приложения чата, получите JSON из синтаксиса onChildAdded () в POJO и вставьте его в свой пользовательский интерфейс. Просто не забудьте удалить слушателя, когда пользователь покидает экран.

onChildChanged () дает все дочернее значение с измененными свойствами (новые).

onChiledRemoved () возвращает удаленный дочерний узел.

Получение данных с разбиением на страницы

Когда у вас есть огромная база данных JSON, добавление прослушивателя событий значения не имеет смысла. Он вернет огромный JSON и разберется, это потребует много времени. В таких случаях мы можем использовать разбиение на страницы и выборку данных, а также их отображение или обработку. Вроде как ленивая загрузка или как выбор старых чатов, когда пользователь нажимает на старую чат. В этом случае может использоваться запрос .

Давайте рассмотрим наш старый пример в предыдущих разделах. В базе пользователей есть 3 пользователя, если он произносит 3 сотни тысяч пользователей, и вы хотите получить список пользователей в партиях по 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
    });

Здесь можно добавить и прослушать значения или дочерние события. Вызовите запрос еще раз, чтобы получить следующие 50. Не забудьте добавить метод orderByChild () , это не будет работать без этого. Firebase должен знать порядок, по которому вы разбиваете страницы.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow