Los datos extraídos de FirebaseDatabase se muestran en 3 AlertDialogs separados en lugar de uno

Estoy buscando algunos datos de FirebaseDatabase y luego ponerlos en una array y luego tratando de mostrarlos en una List que está en un AlertDialog personalizado.

Aquí está el código:

 query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild"); uProfile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { query.orderByChild("someChild").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { if (dataSnapshot != null) { Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue(); ArrayList<String> l = new ArrayList<String>(); l.add(newD.get("lol").substring(30)); String names[] = l.toArray(new String[0]); AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this); LayoutInflater inflater = getLayoutInflater(); View convertView = inflater.inflate(R.layout.dialog_list, null); alertDialog.setView(convertView); alertDialog.setTitle("title"); ListView lv = (ListView) convertView.findViewById(R.id.lv); ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names); lv.setAdapter(adapter); alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); alertDialog.show(); } else { Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show(); } } ... ... }); } }); 

Aquí está la estructura de la base de datos:

 app -child -anotherChild -yetAnotherChild -inaccessibleChild -someChild: "value" -lol: "value" 

No puedo usar valueEventListener() aquí, ya que no tengo acceso a inaccessibleChild . El inaccessibleChild aquí es el uid de los otros usuarios que siguieron a un usuario en particular. ¿Cómo puedo acceder allí uid ?

El problema es que los datos se obtiene pero en lugar de ser mostrado en una lista en un AlertDialog , se está mostrando uno a uno en 3 AlertDialog separado.

¿Qué está pasando mal aquí?

Por favor hagamelo saber.

Las transacciones de Firebase son asíncronas así que su línea inicial para agregar los 3 niños sucede después de que usted fije su oyente, por lo tanto su llamada de llamada se llama 3 veces. (Haciendo 3 diálogos).

Mueva esta línea fuera del clic de clic:

  query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild"); 

Entonces cuando usted agrega el oyente de debajo (dentro del tecleo) debe ser aceptable

 query.orderByChild("someChild").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { 

Cree y muestre el AlertDialog antes de llamar .addChildEventListener ()

A continuación, utilice dentro de addChildEventListener llamar a notifyDatasetChanged () después de descargar los datos apropiados. No cree el AlertDialog dentro del addChildEventListener

Puede utilizar las consultas de Firebase para limitar los datos descargados por un oyente.

 query.orderByChild("someChild").limitToLast(1).addChildEventListener(... 

@ Blundell tiene la idea de resolver su problema. Sólo quiero sugerirle un enfoque similar con addValueEventListener .

El detector de eventos de valor se disparará una vez para el estado inicial de los datos y, a continuación, cada vez que cambie el valor de esos datos.

Necesita mover la consulta firebase de la función onClick . Así que su consulta podría ser así.

 // Declare the variable names as public private String names[]; private void addFirebaseListener() { ref = mDatabase.child("child").child(anotherChild).child("yetAnotherChild"); ref. userRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue(); ArrayList<String> l = new ArrayList<String>(); l.add(newD.get("lol").substring(30)); names[] = l.toArray(new String[0]); // Call notifyDataSetChanged each time your array gets updated adapter.notifyDataSetChanged(); } @Override public void onCancelled(FirebaseError error) { } }); } 

Ahora escriba una función para mostrar el ListView en el AlertDialog

 // Declare the adapter as public and initialize it with null private ArrayAdapter<String> adapter = null; private void showListInDialog() { AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this); LayoutInflater inflater = getLayoutInflater(); View convertView = inflater.inflate(R.layout.dialog_list, null); alertDialog.setView(convertView); alertDialog.setTitle("title"); ListView lv = (ListView) convertView.findViewById(R.id.lv); if(adapter == null) adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names); // Now set the adapter lv.setAdapter(adapter); alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { alertDialog.dismiss(); } }); alertDialog.show(); } 

Ahora, dentro de la función onCreate , onCreate debe configurar el oyente de Firebase y luego establecer la función onClick esta manera.

 uProfile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showListInDialog(); } }); 

@Hammad Pruebe este código modificado basándose en su requisito.

  query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild"); AlertDialog alertDialog; ArrayList<String> l; uProfile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { query.orderByChild("someChild").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { if (dataSnapshot != null) { Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue(); if(l == null) { l = new ArrayList<String>(); } l.add(newD.get("lol").substring(30)); String names[] = new String[l.size()]; for(int length=0; length < l.size(); l++) { names[length] = l.get(length); } if(alertDialog == null) { alertDialog = new AlertDialog.Builder(Activity.this).create(); LayoutInflater inflater = getLayoutInflater(); View convertView = inflater.inflate(R.layout.dialog_list, null); alertDialog.setView(convertView); alertDialog.setTitle("title"); ListView lv = (ListView) convertView.findViewById(R.id.lv); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names); lv.setAdapter(adapter); alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); if(!alertDialog.isShowing()) { alertDialog.show(); } } else { Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show(); } } ... ... }); } }); 

Poner límite cuando estás usando valueEventListener o addChildEventListener . Me gusta esto,

 int limit = 100; databaseRef.child("chats").limitToLast(limit).addValueEventListener(listener); 

Y siempre eliminar el oyente cuando haya hecho con su trabajo relacionado con firebase. Me gusta esto,

 databaseRef.child("chats").limitToLast(limit).removeEventListener(listener); 

Gracias.

 ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey()); 

Todos los derechos reservados

Recuperar listas de elementos o escuchar las adiciones a una lista de elementos. Esta devolución de llamada se activa una vez para cada hijo existente y, a continuación, cada vez que se agrega un nuevo hijo a la ruta de acceso especificada. El DataSnapshot pasado al oyente contiene los datos del nuevo hijo.

** /

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

}; Ref.addChildEventListener (childEventListener); Usando ChildEventListener onChildAdded son llamadas por niño que tiene en ese nodo. Significa que su código se ejecuta 3 veces para que el diálogo aparezca 3 veces.

Este es el problema Así que la solución es:

Si bien el uso de ChildEventListener es la forma recomendada de leer listas de datos, hay situaciones en las que es útil adjuntar un ValueEventListener a una referencia de lista.

Adjuntar un ValueEventListener a una lista de datos devolverá toda la lista de datos como un solo DataSnapshot, que luego se puede hacer un bucle para acceder a los niños individuales.

Incluso cuando sólo hay una coincidencia para la consulta, la instantánea sigue siendo una lista; Sólo contiene un solo elemento. Para acceder al elemento, debe realizar un bucle sobre el resultado:

 inaccessibleChild.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) { //here you can access the each child of that node. } } @Override public void onCancelled(DatabaseError databaseError) { // Getting Post failed, log a message Log.w(TAG, "loadPost:onCancelled", databaseError.toException()); // ... } 

});

Bueno, ninguna de las respuestas anteriores realmente ayudó, aunque la respuesta de Linxy es correcta, lo vi después de resolver el problema.

Mover todo el código y escribir sólo esta línea: alertDialog.show(); Dentro de setOnClickListener() mejorando mi código a esto:

  query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild"); query.orderByChild("someChild").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { if (dataSnapshot != null) { Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue(); ArrayList<String> l = new ArrayList<String>(); l.add(newD.get("lol").substring(30)); String names[] = l.toArray(new String[0]); AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this); LayoutInflater inflater = getLayoutInflater(); View convertView = inflater.inflate(R.layout.dialog_list, null); alertDialog.setView(convertView); alertDialog.setTitle("title"); ListView lv = (ListView) convertView.findViewById(R.id.lv); ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names); lv.setAdapter(adapter); alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); } else { Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show(); } } ... ... }); uProfile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { alert11.show(); } }); 

De todos modos, me gustaría dar las gracias a todos los que respondieron a esta pregunta.

Paz.

  • Paginación del adaptador reciclador Firebase
  • Robolectric app testing con Firebase
  • ¿Cómo puedo permitir que mi aplicación acceda a firebase sin un login?
  • Java.lang.IllegalStateException: Esta función solo está disponible para instancias de backend
  • Agregue al oyente táctil para Firebase RecyclerView
  • Firebase UI RecyclerView onClick
  • Propósito del cliente de la autenticación Firebase de Android de clave de API
  • Cómo excluir el elemento de un FirebaseRecyclerAdapter
  • Cómo usar el valor automático con firebase 9.2 en Android
  • ¿Cómo usar la marca de hora del servidor Firebase para generar la fecha creada?
  • Android: ¿Realmente necesito la autenticación personalizada de Firebase?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.