5

ja ściągam jakieś dane od FirebaseDatabase a następnie umieszczenie ich w array a następnie stara się pokazać ich w List który jest w zwyczaju AlertDialog.Dane pobierane z FirebaseDatabase jest uzyskiwanie pokazano na 3 oddzielnych AlertDialogs zamiast jednego

Oto kod:

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

      ... 
      ... 
     }); 

    } 
}); 

Oto struktura bazy danych:

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

Nie mogę korzystać valueEventListener() tu nie mam dostępu do inaccessibleChild. inaccessibleChild tutaj jest uid innych użytkowników, którzy śledzili danego użytkownika. Jak mogę uzyskać do niego dostęp uid?

Problemem jest to, że dane są coraz idące ale zamiast się widoczne na liście w jednym AlertDialog, jest uzyskiwanie pokazano jeden po drugim w oddzielnym AlertDialog.

Co tu jest nie tak?

Proszę dać mi znać.

+0

ile dzieci jest pod "child/anotherChild/yetAnotherChild"? podłączasz 'ChildEventListener' i wygląda na to, że ma 3 dzieci pod tym węzłem, dlatego' onChildAdded' jest uruchamiany 3 razy (i 'alertDialog.show();' jest wywoływany 3 razy – Wilik

+0

@ Wilik tak ... Tak właśnie się dzieje. "" Pozwól, aby 'alertDialog.show();' był wywoływany tylko 1 raz pokazując wszystkie 3 wartości? –

+0

Odpowiedź Reaza Mursheda stanowi najlepszy przykład, używając 'ValueEventListener' – Wilik

Odpowiedz

1

Żadna z powyższych odpowiedzi naprawdę nie pomogła, chociaż odpowiedź Linxy jest poprawna, zobaczyłem to po rozwiązaniu probelmu.

Moving cały kod na zewnątrz i pisanie właśnie ten wiersz: alertDialog.show(); wewnątrz setOnClickListener() poprawy mojego kodu do tego:

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

W każdym razie, chciałbym podziękować wszystkim, którzy odpowiedzieli na to pytanie.

Pokój.

3

Transakcje w bazie Firebase są asynchroniczne, więc początkowa linia dodawania 3 dzieci dzieje się po ustawieniu odbiornika, dlatego wywołanie zwrotne jest wywoływane 3 razy. (tworzenie 3 okien dialogowych).

Move to linia na zewnątrz z na kliknięcia:

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

Następnie po dodaniu poniższego słuchacza (wewnątrz na kliknięcie) powinno być ok

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

to nie działa. zobacz zaktualizowane pytanie. wciąż otrzymuję 3 dialogi. –

1

Można użyć Firebase zapytania do ograniczyć dane pobierane przez odbiornik.

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

@Blundell ma wgląd w rozwiązanie Twojego problemu. Chcę tylko zaproponować podobne podejście z addValueEventListener.

The value event listener will fire once for the initial state of the data, and then again every time the value of that data changes.

Musisz usunąć zapytanie bazy ogniowej z funkcji onClick. Więc zapytanie może wyglądać tak ..

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

Teraz napisać funkcję, aby pokazać ListView w 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(); 
} 

Teraz wewnątrz funkcji onCreate trzeba ustawić Firebase słuchacza, a następnie ustawić funkcja onClick działa w następujący sposób.

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

zobacz edytowane pytanie .. pokazuje, dlaczego nie mogę użyć 'valueEventListener()'. –

+0

proszę odpowiedzieć .. dzięki. –

+0

'Nie mogę użyć valueEventListener() tutaj, ponieważ nie mam dostępu do niedostępnej" "To nie jest całkiem jasne. Jak chcesz odczytać dane, gdy masz jakiś niedostępny węzeł? –

1

@Hammad Spróbuj zmodyfikować kod w oparciu o swoje wymagania.

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

       ... 
       ... 
      }); 

     } 
    }); 
+0

ten błąd: 'java.lang.IllegalStateException: Określone dziecko ma już element nadrzędny. Musisz najpierw wywołać removeView() na rodzicu dziecka. "Po kliknięciu na' uProfile'. –

+0

Edytowałem moją odpowiedź i dodałem, jeśli (! AlertDialog.isShowing()). W przypadku jakichkolwiek problemów proszę podać dokładną linię problemu. – ChaitanyaAtkuri

+0

nadal ten sam problem ... tutaj na linii 'alertDialog.show();' –

3

granica Put gdy używasz valueEventListener lub addChildEventListener. w ten sposób,

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

Zawsze usuwaj słuchacza, gdy wykonasz swoją pracę związaną z bazą ogniową. w ten sposób,

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

Dzięki.

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

/**

Pobierz wykazy przedmiotów lub słuchać uzupełnień do listy przedmiotów. To wywołanie zwrotne wyzwala się raz dla każdego istniejącego dziecka, a następnie ponownie za każdym razem, gdy nowe dziecko zostanie dodane do podanej ścieżki. DataSnapshot przekazany do detektora zawiera dane nowego dziecka.

**/

} 

@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); Usining ChildEventListener onChildDodano wartość dla każdego dziecka z tego węzła. Znaczy twój kod działa 3 razy, więc okno dialogowe aplikacji 3 razy.

to problem więc rozwiązanie jest:

While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.

Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.

Even when there is only a single match for the query, the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result:

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

});

2

Tworzenie i pokazać AlertDialog przed wywołaniem .addChildEventListener()

Następnie użyj wewnątrz addChildEventListener zadzwonić notifyDatasetChanged() po pobraniu odpowiednich danych. Nie twórz AlertDialog wewnątrz addChildEventListener