Продолжайте вставлять новые данные в существующий массив в базе данных Firebase с Android

Я только начинаю изучать студию Android и работаю над проектом, основанным на местоположении, чтобы вставить информацию о местоположении в Firebase. Я следовал руководству с YouTube [https://www.youtube.com/watch?v=CwxdfamaCrk], однако в видео показаны только вставляемые данные из кода, похожего на этот;

infectedArea = new ArrayList<>();
    infectedArea.add(new LatLng(2.2258162, 102.4497224));
    infectedArea.add(new LatLng(2.2252313, 102.4563797));
    infectedArea.add(new LatLng(2.2261818, 102.4551067));
    infectedArea.add(new LatLng(2.275295,102.444035));

    FirebaseDatabase.getInstance()
            .getReference("InfectedArea")
            .child("Location")
            .setValue(infectedArea)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
                }
            }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });

Ниже приведены снимки моей firebase.

введите здесь описание изображения

Из кода вставляются те, что с индексом 0, 1, 2 и 3. Теперь я пытаюсь продолжить вставку данных из формы ввода, но был сгенерирован случайный ключ, и новая геозона не может быть создана. Есть ли способ продолжить вставку данных с аппаратным ключом?

Я думал удалить аппаратный ключ и просто использовать сгенерированный ключ, но тогда я понятия не имею, как изменить код для создания нескольких геозон.


person Nabella    schedule 12.12.2019    source источник
comment
Firebase намеренно не предлагает операции для вставки элементов с последовательным числовым ключом. См. firebase.google.com/docs/database/android/structure-data, firebase.googleblog.com/2014/04 / и stackoverflow.com/questions/39519021/   -  person Frank van Puffelen    schedule 13.12.2019


Ответы (2)


он будет накапливаться в HashMap, поэтому вы можете getkey получить случайный ключ, и вы получите случайный ключ, в который вы можете вставить данные

DatabaseReference database = FirebaseDatabase.getInstance().getReference("InfectedArea").child("Location");
    database_course.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            for(DataSnapshot ds :dataSnapshot.getChildren()){
               String key = ds.getKey();
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
person Ruyut    schedule 12.12.2019

Firebase намеренно не предлагает операции для вставки элементов с последовательным числовым ключом. Видеть:

При этом вы можете использовать массивоподобные структуры с последовательными числовыми индексами, а также можете использовать автоматические идентификаторы. Итак, давайте рассмотрим каждый по очереди.


Использование последовательных числовых индексов

Чтобы добавить новый элемент с ключом 4 в вашу текущую структуру, вам необходимо:

  1. Определить самый высокий ключ
  2. Добавить дочерний узел на один ключ выше

В простейшем формате это выглядит так (на Android):

FirebaseDatabase.getInstance()
        .getReference("InfectedArea")
        .child("Location")
        .runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData mutableData) {
        String lastKey = "-1";
        for (MutableData child: mutableData.getChildren) {
            lastKey = child.getKey();
        }

        int nextKey = Integer.parseInt(lastKey) + 1;

        mutableData.child("" + nextKey).setValue("your next value here");

        // Set value and report transaction success
        return Transaction.success(mutableData);
    }

    @Override
    public void onComplete(DatabaseError databaseError, boolean b,
                           DataSnapshot dataSnapshot) {
        // Transaction completed
        Log.d(TAG, "Transaction:onComplete:" + databaseError);
    }
});

Как видите, кода довольно много. Это в значительной степени необходимо, потому что несколько пользователей могут получать доступ к одному и тому же местоположению почти в одно и то же время, и нам нужно справиться с этим. Firebase использует оптимистическую блокировку, но описанное выше может стать серьезным узким местом при наличии нескольких пользователей. Плюс: это намного сложнее, чем ваш простой push().setValue(...).


Используйте автоматические идентификаторы для исходного набора данных и для новых данных.

Вы можете легко записать все точки с push-идентификаторами (это ключи, которые генерирует push()), как только вы поймете, что вызов только push() еще не записывает в базу данных. Вы можете получить новый push-идентификатор в чистом коде Android с помощью:

String pushID = ref.push().getKey();

Зная это, мы можем изменить ваш код, чтобы вставить начальные местоположения в:

DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
// It doesn't matter what the reference points to, as push IDs are statistically guaranteed to be unique, independent of their location.

Map<String, Object> values = new HashMap<>();
infectedArea.put(ref.push().getKey(), new LatLng(2.2258162, 102.4497224));
infectedArea.put(ref.push().getKey(), new LatLng(2.2252313, 102.4563797));
infectedArea.put(ref.push().getKey(), new LatLng(2.2261818, 102.4551067));
infectedArea.put(ref.push().getKey(), new LatLng(2.275295,102.444035));

FirebaseDatabase.getInstance()
        .getReference("InfectedArea")
        .child("Location")
        .setValue(values)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
            }
        }).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
    }
});

Это приведет к структуре, аналогичной той, которую вы знаете, но со всеми ключами, являющимися идентификаторами push.

person Frank van Puffelen    schedule 13.12.2019
comment
ваш пример показывает, как вставить данные из кода, но что, если я хочу вставить данные из формы ввода? - person Nabella; 13.12.2019
comment
В этом случае вы бы прочитали данные из кода и построили бы из них карту. Но ваш вопрос также показывал проблему в коде, так что я ответил. - person Frank van Puffelen; 13.12.2019