Данные, полученные из FirebaseDatabase, отображаются в 3 отдельных AlertDialogs вместо одного

Я извлекаю некоторые данные из FirebaseDatabase и затем помещаю их в array а затем пытаюсь показать их в List который находится в пользовательском AlertDialog .

Вот код:

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

Вот структура базы данных:

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

Я не могу использовать valueEventListener() здесь, так как у меня нет доступа к inaccessibleChild valueEventListener() . inaccessibleChild здесь является uid других пользователей, которые следовали за конкретным пользователем. Как я могу получить доступ к нему?

Проблема в том, что данные AlertDialog , но вместо того, чтобы отображаться в списке в одном AlertDialog , он отображается один за другим в 3 отдельных AlertDialog .

Что здесь происходит?

Пожалуйста, дайте мне знать.

Операции Firebase являются асинхронными, поэтому ваша начальная строка для добавления трех детей происходит после того, как вы установили слушателя, поэтому ваш обратный вызов вызывается 3 раза. (Создание 3 диалоговых окон).

Переместите эту строку за пределы щелчка:

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

Затем, когда вы добавляете ниже слушателя (внутри клика), он должен быть в порядке

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

Создайте и покажите AlertDialog перед вызовом .addChildEventListener ()

Затем используйте внутри addChildEventListener вызов notifyDatasetChanged () после того, как вы скачали соответствующие данные. Не создавайте AlertDialog внутри addChildEventListener

Вы можете использовать Firebase Queries для ограничения данных, загружаемых слушателем.

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

@Blundell имеет представление о решении вашей проблемы. Я просто хочу предложить вам аналогичный подход с addValueEventListener .

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

Вам нужно вытащить запрос onClick из функции onClick . Таким образом, ваш запрос может выглядеть так.

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

Теперь напишите функцию, чтобы показать ListView в 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(); } 

Теперь внутри вашей функции onCreate вам нужно сначала установить прослушиватель Firebase, а затем установить onClick как это.

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

@Hammad Попробуйте этот модифицированный код, основываясь на ваших требованиях.

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

Положите ограничение, когда вы используете valueEventListener или addChildEventListener . как это,

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

И всегда удаляйте слушателя, когда вы делали с вашей работой, связанной с firebase. как это,

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

Благодарю.

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

/ **

Получить списки элементов или прослушать добавления в список элементов. Этот обратный вызов запускается один раз для каждого существующего дочернего элемента, а затем снова каждый раз, когда новый ребенок добавляется к указанному пути. DataSnapshot, переданный слушателю, содержит данные нового ребенка.

** /

 } @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); Использование ChildEventListener onChildAdded – это вызов на каждого ребенка, который у вас есть на этом узле. Означает, что ваш код запускается 3 раза, поэтому диалоговое окно 3 раза.

Это проблема. Итак, решение:

Хотя использование ChildEventListener является рекомендуемым способом для чтения списков данных, бывают ситуации, когда привязка ValueEventListener к ссылке на список является полезным.

Прикрепление ValueEventListener к списку данных вернет весь список данных как один DataSnapshot, который вы затем можете перебирать для доступа к отдельным детям.

Даже если для запроса имеется только одно совпадение, моментальный снимок по-прежнему является списком; Он просто содержит один элемент. Чтобы получить доступ к элементу, вам необходимо выполнить цикл по результату:

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

});

Ну, ни один из вышеперечисленных ответов не помог, хотя ответ Linxy правильный, я увидел его после решения проблемы.

Перемещение всего кода и запись только этой строки: alertDialog.show(); Внутри setOnClickListener() улучшает мой код:

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

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

Мир.