Почему значение элемента добавляется дважды при переборе базы данных firebase в Kotlin? - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь перебрать firebase-database и добавить его элементы в мой объект.Это работает, но по какой-то причине я не понимаю, он дважды рекламирует каждый элемент, вывод журнала показывает что-то вроде этого:

TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Tahini-Oat Cookies } 
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Tahini-Oat Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Chocolate & Cinnamon Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Chocolate & Cinnamon Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Sweet Potato Muffin }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Sweet Potato Muffin }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Almond Butter Cookies }
TAGZ: DataSnapshot { key = recipeHeaderFirebase, value = Almond Butter Cookies }

Структура Firebase-database выглядит следующим образом (обратите внимание, что я проигнорировалдругие элементы на данный момент):

FbDb

Мой код Kotlin выглядит следующим образом:

fbdb = FirebaseDatabase.getInstance()
ref = fbdb!!.getReference("cookies")

ref!!.addChildEventListener(object: ChildEventListener {

    override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) {
        val children = snapshot!!.children //DIRECT REFERENCE TO CHILD, USED FOR LOOP
        val header = snapshot!!.child("recipeHeaderFirebase")

        for(it in children) {
            var tempRecipe = RecipeTemplate()
            tempRecipe.recipeHeader = header.toString()
            Log.d("TAGZ", tempRecipe.recipeHeader)  //OUTPUT SHOWS DUPLICATE VALUES
            }
        }
    }) 

Чего мне не хватает?Я успешно извлекаю элементы в Xcode, используя подобный код ...

РЕДАКТИРОВАТЬ ПОЛНЫЙ КОД ПО ЗАПРОСУ:

package com.healthandchocolate.sjostedtafzelius.healthchocolateandroid

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.google.firebase.database.*

class RecipeGridView : AppCompatActivity() {

private var fbdb: FirebaseDatabase? = null
private var ref: DatabaseReference? = null
var recipeArray: MutableList<RecipeTemplate> = mutableListOf()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_recipe_grid_view)
    Log.d("TAG", "ON CREATE");

    fbdb = FirebaseDatabase.getInstance()
    ref = fbdb!!.getReference("cookies")

    ref!!.addChildEventListener(object: ChildEventListener {

        override fun onChildChanged(snapshot: DataSnapshot?, p1: String?) {

        }

        override fun onChildMoved(p0: DataSnapshot?, p1: String?) {
            Log.d("TAG", "ON CHILD MOVED");
        }

        override fun onChildRemoved(p0: DataSnapshot?) {
            Log.d("TAG", "ON CHILD REMOVED");

        }

        override fun onCancelled(error: DatabaseError) {
            print(error)
            Log.d("TAG", "ON ERROR");

        }

        override fun onChildAdded(snapshot: DataSnapshot?, p1: String?) {
            Log.d("TAGZ", "CALLED")  //keyName of each child

            val children = snapshot!!.children //DIRECT REFERENCE TO CHILD, USED FOR LOOP
            val header = snapshot!!.child("recipeHeaderFirebase")

            for(it in children) {
                var tempRecipe = RecipeTemplate()
                tempRecipe.recipeHeader = header.toString()
                //Log.d("TAGZ", tempRecipe.recipeHeader)  //keyName of each child

                recipeArray.add(tempRecipe)
            }
        }
        }) //END FB CODE
}
}

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Правильный способ сделать это - переместить код, который добавляет ChildEventListener из onCreate в функцию fun attachValueEventListener() за пределами onCreate.

Затем присоедините прослушиватель в методе onStart..

override fun onStart() {
    super.onStart()
    // add an event listener to watch changes in firebase database
    attachValueEventListener()
}

... и отключите слушателя в onStop

override fun onStop() {
    super.onStop()
    // detach the event listener that watches changes in firebase database
    detachValueEventListener()
}

private fun detachValueEventListener() {
    if (mValueEventListener != null) {
        myRef?.removeEventListener(mValueEventListener)
        mValueEventListener = null
    }
}

Вам также нужно будет объявить

private var mValueEventListener: ValueEventListener? = null
0 голосов
/ 18 мая 2018

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

Каждый раз, когда вызывается ваша функция, функция обратного вызова, которую вы удерживаете для события addChildEventListener, добавляется к слушателю.После этого, когда событие инициируется, функция обратного вызова вызывается столько, сколько она была связана с прослушивателем ранее.

Чтобы предотвратить это поведение, вы можете определить android:launchmode:"singleTop" в файле манифеста приложения втег <activity>

Это позволяет системе направлять намерения на другую функцию onNewIntent вместо onCreate

Для получения дополнительной информации ознакомьтесь с: https://developer.android.com/guide/topics/manifest/activity-element#lmode

Надеюсь, это поможет.

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

...