Daten im Recyclerview anzeigen (Firebase)

  • Antworten:16
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 17

16.10.2018, 22:31:51 via Website

Hey,

Habe direkt ein paar Fragen. Hoffentlich ist das okay. Möchte nicht drei verschiedene Threads aufmachen.

Also zu meiner App.
Die App besteht darin, dass man Wörter in eine Firebase Datenbank lädt und dass diese danach in einer Ranking Activity dargestellt werden. Nutzer können über die Wörter abstimmen. Eine Variable zählt die up und down votes dann.

Daten laden funktioniert, das up und down voten auch.
Hier mal der Code:

private RecyclerView recycleRank;
private LinearLayoutManager layManRank;
private FirebaseRecyclerAdapter<Word, RankingActivity.RankingViewHolder> recAdapterRank;

...

DatabaseReference personsRef = FirebaseDatabase.getInstance().getReference("Word");
Query personsQuery = personsRef.orderByChild("count");

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

....

recAdapterRank = new FirebaseRecyclerAdapter<Word, RankingViewHolder>(personsOptions) {
    @Override
    protected void onBindViewHolder(RankingActivity.RankingViewHolder holder, final int position, final Word model) {
        holder.setWord(model.getWord());
        long score = model.getCount();
        holder.setScore(String.valueOf(score));
        holder.setRank(String.valueOf(holder.getAdapterPosition()));
    }

Nun zu den Fragen.

  1. Mit .setReverseLayout zeigt es mir das Ranking richtig an. Ohne das, ist die niedrigste Zahl ganz oben und die höchste ganz unten. Das macht ja weniger Sinn.
    So nun möchte ich aber mit holder.setRank(String.valueOf(holder.getAdapterPosition()));
    die Platzierung des Wortes angeben. Dadurch, dass aber .setReverseLayoutgesetzt ist, sieht das ganze so aus:

    Nr Word Score
    2 Tree 12
    1 Wood 9

es sollte aber so aussehen:

Nr Word Score 
1 Tree 12 
2 Wood 9

Wie kann man das lösen? Mit einem String Array? Oder geht das einfacher?

  1. Wie geht das, dass die Ranking Activity nur 100 Wörter fassen kann?
    Mit personsQuery .limitToFirst(100); funktioniert das irgendwie nicht. Es werden einfach alle Einträge geladen.

  2. Wie kann man eine Progressbar setzten, während die Daten laden? Bekomme das einfach nicht hin. Dachte mit einem Handler, aber irgendwie will das nicht so richtig.

Das wäre es einmal.
Sorry für den langen Text.

Es wäre super, wenn mir jemand helfen könnte. Komme einfach nicht weiter.

Vielen Dank im Voraus! :)

Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 484

17.10.2018, 11:06:26 via Website

Hallo ich habe noch mal nachgesehen Firebase kann leider nicht eine liste in umgekehrter Reihenfolge erstellen. Die liste wird somit immer beim kleinsten count beginnen.

Da kannst du nur richtigerweise die liste im RecyclerView umdrehen .
Nun müsstest du aber auch dein Rank verändern. Die AdapterPosition nützt dir da nicht allzu viel da er die liste von unten durchgeht. Entweder du zählst dein rank selber Hoch.
Oder du ziehst von der Anzahl der Eintrage die Position ab.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

17.10.2018, 08:36:03 via Website

Hallo
Zeige uns mal wie du deine Querey „personsQuery“ auswertest und somit dem Adapter übergibst. Interessant währe auch wie deine DB Struktur aussieht.
Was du gepostet hast Reicht leider nicht um da eine Aussaget zu treffen.

Mit .setReverseLayout zeigt es mir das Ranking richtig an. Ohne das, ist die niedrigste Zahl ganz oben und die höchste ganz unten. Das macht ja weniger Sinn.
So nun möchte ich aber mit

setReverseLayout zeigt dir nur deine liste die du dem Adapter übergeben hast in anderer Richtung an. Entweder du fragst diene DB gleich so ab das du es schon in der richtigen Reihenfolge hast. Oder du sortierst die Daten selber bei auswerten der Query und Übergibst sie somit in der richtigen Reihenfolge am den Adapter.

Wie geht das, dass die Ranking Activity nur 100 Wörter fassen kann?
Mit personsQuery .limitToFirst(100); funktioniert das irgendwie nicht. Es werden einfach alle Einträge geladen.

„ limitToFirst(100)“ ist ein Filter den du bei der Query abfrage einsetzen musst, der gibt die die ersten 100 gefundenen Entränge aus .
Query personsQuery = personsRef.orderByChild("count").limitToFirst(100);

Wie kann man eine Progressbar setzten, während die Daten laden? Bekomme das einfach nicht hin. Dachte mit einem Handler, aber irgendwie will das nicht so richtig.

Auch hier wäre wichtig zu wissen wie du deine Query auswertest.

— geändert am 17.10.2018, 09:05:38

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 17

17.10.2018, 09:18:05 via Website

Hi,

danke für Deine Antwort! :)

Das mit dem limitToFirst hat geklappt. Dachte, dass das erst unten gesetzt wird. Danke!

Hier einmal alles, was mit dem RecyclerView zu tun hat:

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

    recAdapterRank = new FirebaseRecyclerAdapter<Word, RankingViewHolder>(personsOptions) {
        @Override
        protected void onBindViewHolder(RankingActivity.RankingViewHolder holder, final int position, final Word model) {
            holder.setWord(model.getWord());
            long score = model.getCount();
            holder.setScore(String.valueOf(score));
            holder.setRank(String.valueOf(holder.getAdapterPosition()));
        }

        @Override
        public RankingActivity.RankingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.ranking_row, parent, false);

            return new RankingActivity.RankingViewHolder(view);
        }
    };

 //Hier eine addOnItemTouchListener Methode, um eine Aktion beim Klick auf einen Eintrag auszuführen. 
recycleRank.addOnItemTouchListener(new RecyclerItemClickListener(this, recycleRank,
            new RecyclerItemClickListener.OnItemClickListener() {
.....
}

recycleRank.setAdapter(recAdapterRank);
}

Und dann noch:

public static class RankingViewHolder extends RecyclerView.ViewHolder {
    View mView;

    public RankingViewHolder(View itemView) {
        super(itemView);
        mView = itemView;
    }

    public void setRank(String rank) {
        TextView postRank = (TextView) mView.findViewById(R.id.post_rank);
        postRank.setText(rank);
    }

    public void setWord(String Word) {
        TextView postWord= (TextView) mView.findViewById(R.id.post_word);
        postWord.setText(word);
    }

    public void setScore(String score) {
        TextView postScore = (TextView) mView.findViewById(R.id.post_score);
        postScore.setText(score);
    }
}

Ja das war glaub alles.

Und noch die Firebasestruktur:

image

Hilfreich?
Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 484

17.10.2018, 11:06:26 via Website

Hallo ich habe noch mal nachgesehen Firebase kann leider nicht eine liste in umgekehrter Reihenfolge erstellen. Die liste wird somit immer beim kleinsten count beginnen.

Da kannst du nur richtigerweise die liste im RecyclerView umdrehen .
Nun müsstest du aber auch dein Rank verändern. Die AdapterPosition nützt dir da nicht allzu viel da er die liste von unten durchgeht. Entweder du zählst dein rank selber Hoch.
Oder du ziehst von der Anzahl der Eintrage die Position ab.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 2.902

17.10.2018, 12:30:07 via Website

Ich arbeite zwar nicht mit der Firebase Db aber wird ASC / DESC nicht auch mit dem Direction.DESCENDING angebeben ??

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 2.902

17.10.2018, 13:04:52 via Website

EDIT : Mein post hier war quatsch - Jokel hat es selbst gefunden :-)

— geändert am 17.10.2018, 13:07:26

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

17.10.2018, 13:24:27 via Website

@swa00
Ich bin mir aber mit OderByChild nicht sicher ob es da auch geht. Denn ich hatte mal gelesen das da nur eine Reihenfolge gibt. Quelle weis ich nicht mehr. Auch die Methode mit zwei übergabe Werten kann ich nicht in der Doku finden.

Wir sprechen hier von den erweiterten Metoden "oderByChild" und nicht der "oderBy" wo eine Reverse Sortierung möglich ist.

https://firebase.google.com/docs/database/web/lists-of-data#sort_data

somit müste es wohl heisen.
Query personsQuery = personsRef.orderBy("count", Direction.DESCENDING);

— geändert am 17.10.2018, 18:36:46

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

17.10.2018, 15:27:40 via Website

Also orderByChild läst leider keine Reverse Sortierung zu.
Quelle
https://medium.com/@mvuksano/advanced-queries-in-firebase-a50f563179dd

Sort by firstName in reverse
Unfortunately, Firebase does not have a facility to sort in reverse order. You will have to query and get elements in ascending order and then reverse the list. Or another option would be to, as you receive elements, to push them at the beginning of some list rather then the end. Anyways, you get the point — you have to do this yourself somehow.

— geändert am 17.10.2018, 18:32:18

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 17

17.10.2018, 16:43:33 via Website

Danke Leute für eure Hilfe!

Mit 100 - holder.getAdapterPosition();hat es funktioniert! Danke :)
Das andere funktioniert leider nicht.

Habt Ihr mir vielleicht noch eine Lösung für den Progressbar oder Loadingscreen?

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 17

19.10.2018, 19:09:07 via Website

Ok also habe es nun einmal versucht mit der ProgressBar.
Habe das hier einmal versucht:

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

        insults.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;
    }
}

Leider wird der RecyclerView geladen und der ProgressBar läuft weiter.
Was mache ich falsch?

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

21.10.2018, 18:27:27 via Website

Wo wird die Variable "progressbarde" erstellt?
Ist die überhaupt in der Klasse sichtbar zeige das mal.

Ist die asynctask Klasse eine innere Klasse?

Auch das progressbarde.setVisibility(View.INVISIBLE);
Gehört nicht in die doinbackround . Kein Zugriff auf view Elemente im thread. Wird wohl gar nicht sichtbar sein sonnt würde die App abstürzen.

— geändert am 21.10.2018, 19:02:51

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 17

23.10.2018, 14:56:09 via Website

So jetzt. Sorry für die späte Antwort.

Habe in meiner 'onCreate()' eine 'initView();' und in der lese ich dann den Progressbar ein.

Der Vollständigkeit halber:

'progressbarde = (ProgressBar)findViewById(R.id.progressbarde);'

Die Async ist eine innere Klasse, ja.

Die Klasse wird dann so aufgerufen.

    private myTask mytask = new myTask();

    .... //dann in der onCreate()
    mytask.execute(null,null,null);
Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

23.10.2018, 17:40:00 via Website

Also was erstmal nicht sinnvoll ist das du in einem Thread (doinbackround) eine Callback methode machst.
Du kannst in der Callback einen Thread starten und in diesen deine Progressbar anzeigen .
Auch kannst du in dem Thread die daten aus der DB in den Adapter lesen.
Was bringt es dir wenn du den Task einfach Prophylaktisch in der onCreate startest.

Aber da du ja den FirebaseRecyclerAdapter über die FirebaseRecyclerOptions füllst hast du gar keinen Einfluss darauf.

Hier wüsste ich nicht wie du da eine Progressbar reinbasteln willst.
Denn der Abfrage Listner steckt hier in deinen Adapter.

Kann dir da nicht viel helfen da ich den Adapter nicht kenne. Was der alles für Möglichkeiten hat.
Und wo oder wie du da einen Verlaufsbalken reagieren kannst.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 17

24.10.2018, 09:12:12 via Website

Hm ok schade.

Geht das dann, dass es bereits beim Start der App abgerufen wird? Also habe ein Homescreen wo nur vier Button sind - einer davon führt eben zu dem Ranking mit dem Recyclerview. Dort sollte es ja dann funktionieren, weil ja nichts in den RecyclerView mit FirebaseRecyclerOptions geladen wird.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 484

24.10.2018, 13:54:37 via Website

Also deine progressbar Wort mit start des asynctask gestartet. Wo wann oder durch welches Ereignis du den startest ist deine Sache.
Nun hast du zwei Möglichkeiten entweder du beendest den task auch bei einem Ereignis Ablauf einer Methode. Im ui thread.
Oder du machst etwas in der doInBackground Methode was selber zu Ende geht und somit auch denn thread beendet.

Hilfreich?
Diskutiere mit!

Empfohlene Artikel