Daten von Firebase mit Progressbar in RecyclerView laden

P

prof.dopenudel

Neues Mitglied
Threadstarter
Hi Leute,

als erstes...der Titel ist ein bisschen blöd, aber wusste nicht, was ich schreiben soll.

Zu meiner Frage/meinen Fragen.

Möchte einen Progressbar laufen lassen, solang die Daten in den RecyclerView geladen werden.

Hier ist mal ein Versuch, der leider nicht funktioniert. Nachdem der RecyclerView mit den Daten bestückt ist, verschwindet der Ladebar nicht.

Code:
class myTask extends AsyncTask<Object, Object, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressbarde.setVisibility(View.VISIBLE);

        progressbarde.setMax(100);

    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        progressbarde.setVisibility(View.GONE);

    }

    @Override
    protected void onProgressUpdate(Object... values) {
        super.onProgressUpdate(values);

        progressbarde.setProgress((Integer) values[0]);
    }

    @Override
    protected Void doInBackground(Object... voids) {

        words.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                Iterable<DataSnapshot> children = dataSnapshot.getChildren();

                int count=0;

                for (DataSnapshot child : children) {

                    count++;
                    if (count >= dataSnapshot.getChildrenCount()) {
                        //stop progress bar here

                        progressbarde.setVisibility(View.INVISIBLE);

                        recycleRank.setVisibility(View.VISIBLE);
                    }
                }
            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

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

            }
        });
        return null;
    }
}
Hier die Firebase Struktur (siehe Anhang)


So noch eine Frage.
Ist es möglich, einen Report - Meldenfläche - zu erstellen. Also ja gut, das habe ich schon, dass wenn man auf einen Eintrag klickt sich ein Menü öffnet, wo man gefragt wird, ob man das Wort melden möchte.
Also nehmen wir an, jemand fügt was rassistisches oder so in die Datenbank (kann und möchte nicht jeden Tag die Datenbank durchschauen). Wie kann man das machen, dass ein Nutzer so ein Wort melden kann?

Mit einer EntwicklerApp, die solche Nachrichten von den NutzerApps erhält? Oder über eine Email Benachrichtigung?
Dazu finde ich leider nichts im Internet.

Danke schon einmal im Voraus !

Grüße
 

Anhänge

Zuletzt bearbeitet:
J

jogimuc

Erfahrenes Mitglied
Hallo

Schaue mal hier AsyncTask zur Entlastung des Main-Threads

Deine onProgressUpdate Methode wird ja gar nicht aufgerufen. Somit wird auch der vorschrittsBalken nicht laufen. Dazu müsstest du auch
publishProgress benuztzen.
in deiner onPostExecute soltte eigentlich deine Progressbar wieder unsichtbar werden.
hast du getestet ob die methode uberhaupt aufgerufen wird? benutze dafür ein Log.
Ist deine progressbarde Variable da überhaupt sichtbar nach OOP?
Wo und wie wird deine progressbarde Variable erstellt?
 
P

prof.dopenudel

Neues Mitglied
Threadstarter
Hey,

danke für Deine Antwort.
Leider verstehe ich das noch nicht so ganz.

Also in dem Link steht ja, dass als erstes die preExecute gestartet wird. Muss ich dann nicht die aufrufen?
Habe einmal alle Methoden geloggt. Wenn ich die preExecute starte, bekomme ich von dieser den Log, von den anderen aber nicht. Heißt, es startet nur diese Methode. Aber die anderen sollten doch automatisch gestartet werden? Oder verstehe ich das falsch? Sorry dafür :D

Progressbar wird so erstellt:
private ProgressBar progressbarde;

und danach eben initialisiert
progressbarde = (ProgressBar)findViewById(R.id.progressbarde);

Das passiert aber in der MainKlasse und nicht in der Async Klasse. Muss die dort rein?

Danke noch mal
 
J

jogimuc

Erfahrenes Mitglied
Ich glaube du hast das Prinzip mit Asynctask noch nicht verstanden. Wahrscheinlich das ganze Thread Thema.

Wo starrtest du denn den Task? Auch macht das keinen sinn den onChildListner in der doInBackground zusetzen .

In der gesamte Leistner gehört nicht in die Asynctask. In der onChildAdded kannst du den Asynctask starten und somit auch deine Progessbar. Von mir aus kannst du auch das auslesen des dataSnapshot mit in die doInBackground verfrachten musst aber somit das Snapshot der Methode mit übergeben.

Der Listner bleibt in der Activity und die anderen Methoden auch.

Wie soll denn sonst das System die Callback Methode aufrufen.

Den Task startest du in dem du eine Instanz von deiner Asynctask Klasse erstellt hast durch den Aufruf von execute(….);

myTask mtask = new myTask();

mtask.execute(null,null,null);



die Methoden der Asynctask werden nicht von Hand aufgerufen das ist falsch.
 
P

prof.dopenudel

Neues Mitglied
Threadstarter
Hey, danke nochmals. Auch für deine Mühe mir das zu erklären :D
Leider verstehe ich das tatsächlich noch nicht so wirklich.

Also habe die preExecute mit

mytask.onPreExecute();

aufgerufen, aber das war ja falsch...okay.

Das Ding ist jetzt. Also weiter oben fülle ich meinen Recyclerview wie folgt:

Code:
private FirebaseRecyclerAdapter<Wort, RankingActivity.RankingViewHolder> recAdapterRank;
...
recAdapterRank = new FirebaseRecyclerAdapter<Wort, RankingActivity.RankingViewHolder>(personsOptions) {
                @Override
                protected void onBindViewHolder(RankingActivity.RankingViewHolder holder, final int position, final Wort model) {
                    holder.setWort(model.getWort());
                    long score = model.getAnzahl();
                    holder.setScore(String.valueOf(score));
                    int realRank = 100 - holder.getAdapterPosition();
                    holder.setRank(String.valueOf(realRank));
                }
...
recycleRank.setAdapter(recAdapterRank);
Den Task starte ich in der onCreate.

In der onChildAdded kannst du den Asynctask starten und somit auch deine Progessbar.
Das Ding ist, dass ich den onChildAdded quasi nur genommen habe, um zu schauen, ob die Daten angekommen sind. Das geht vielleicht auch besser. Die onChildAdded kommt im restlichen Code nicht mehr vor.
Wo soll ich den Asynctask genau starten dann?

Der Listner bleibt in der Activity und die anderen Methoden auch.

Wie soll denn sonst das System die Callback Methode aufrufen.
Also wie gesagt. Der Listner in der DoInBackground ist sonst nirgends vergeben.

Wird der Aufruf von Asynctask jetzt in die onBindViewHolder Methode gepackt?
Sorry kann es gerade nicht testen. Erst morgen wieder, deshalb frage ich so blöd.
 
J

jogimuc

Erfahrenes Mitglied
Da du dein Recyclerview mithilfe des FirebaseRecyclerAdapter füllst hast du eigentlich gar keine richtige Möglichkeit eine Progressbar anzuzeigen.

Das in der onBind zu machen ist aus meiner Sicht falsch und etwas sinnlos. Denn die wird vom Recycler aufgerufen um die Elemente aus dem Adapter zu lesen, und anzuzeigen.

Zu diesen Zeitpunkt sind die Daten normalerweise schon in dem Adapter.

Eine Progressbar macht aus meiner Sicht nur zu der Zeit Sinn, wenn die Daten aus der DB in den Adapter gelesen werden.

Da du das nicht selber in einem Listner machst, sondern das der FirebaseRecyclerOptions überlässt, kannst du auch nicht darauf Einfluss nehmen.
Um zB einen Fortschritts Balken anzuzeigen.

In einem Listner könntest du den Asynctask mit der Progressbar starten, und beim verlassen des Lintner, wenn alle Daten aus der DB in dem Adapter sind, wieder beenden.

Mit diesem Adapter kenne ich mich nicht aus.

Eigentlich optimiert der Adapter schon die Ladezeitn aus der DB. So dass da auch bei 200 Einträgen keine allzugroße warte Zeit entsteht. Wie du den Adapter abfragen kannst ob er fertig ist weiß ich nicht.

Den Asyncktast einfach ohne ein Ereignis in der onCreate zu starten macht keinen sinn.
Sondern den würde ich bei deiner ersten variante in dem Listner starten und wieder beenden.
 
Zuletzt bearbeitet:
P

prof.dopenudel

Neues Mitglied
Threadstarter
Hm schade, das hört sich jetzt nicht so gut an :D

Code:
recycleRank.hasFixedSize();
            layManRank = new LinearLayoutManager(this);
            layManRank.setReverseLayout(true);
            layManRank.setStackFromEnd(true);
            recycleRank.setLayoutManager(layManRank);

            registerForContextMenu(recycleRank);

            swipeRefreshLayout.setOnRefreshListener(this);

            FirebaseRecyclerOptions personsOptions = new FirebaseRecyclerOptions.Builder<Wort>().setQuery(personsQuery,
                    Wort.class).build();

            recAdapterRank = new FirebaseRecyclerAdapter<Wort, RankingActivity.RankingViewHolder>(personsOptions) {
                @Override
                protected void onBindViewHolder(RankingActivity.RankingViewHolder holder, final int position, final Wort model) {
                    holder.setWort(model.getWort());
                    long score = model.getAnzahl();
                    holder.setScore(String.valueOf(score));
                    int realRank = 100 - holder.getAdapterPosition();
                    holder.setRank(String.valueOf(realRank));
                }
Die Daten werden halt so in den Recyclerview geladen, da so eine Liste gemacht werden kann. Oder geht das anders? So funktioniert es, und deshalb dachte ich, dass das schon passt.

In einem Listner könntest du den Asynctask mit der Progressbar starten, und beim verlassen des Lintner, wenn alle Daten aus der DB in dem Adapter sind, wieder beenden.
Mit welchem Listener könnte man das machen?
Also es soll nicht unbedingt ein Balken mit dem Fortschritt laufen. Es reicht, wenn ein Kreis läuft, der eben solange läuft, bis die Daten geladen sind.
Wie der Progressbar als Kreis dargestellt wird, weiß ich, aber es fehlt eben das er angezeigt wird, wenn die Daten geladen werden.

Aber scheinbar geht das ja dann wohl nicht.


Nur mal so noch.

Also nehmen wir an, jemand fügt was rassistisches oder so in die Datenbank (kann und möchte nicht jeden Tag die Datenbank durchschauen). Wie kann man das machen, dass ein Nutzer so ein Wort melden kann?

Mit einer EntwicklerApp, die solche Nachrichten von den NutzerApps erhält? Oder über eine Email Benachrichtigung?
Wie sieht es damit aus? Das sollte doch funktionieren?
 
Oben Unten