Okay ist auch glaube ich etwas zu umfangreich um mal eben darauf eine antwort zu geben
Auf jedenfall schonmal danke das du dir die Zeit für mich nimmst
Firebase überträgt Daten nicht richtig?
-
-
Hallo
Habe es mir nur kurz angesehen. Konnte die App nicht Starten da einige Drawable fehlen. Und ich habe andere genommen.
Um es zu testen müsste ich mich aber an deiner DB anmelden habe ich noch nicht.
Noch mal etwas zum Grund Verständnis deiner APP.
Es ist so das nur der Admin die Zeit Starten und Stoppen kann. Richtig?
Wo in welcher Klasse und Methode machter das . Wie macht erdas ich denke in einem onClicklistner nicht in einem ValueEventListener. Hoffe ich zu mindestens damit meine ich den teil wo die Daten in die DB geschrieben werden.
Was kann der Teilnehmer machen? Wo kann er Daten in die DB eingeben? Wenn ja welche?
Macht er das bewusst in einen OnClickListner?
Wie wird die Methode von gestern ZeitBerechnung aus gelöst?
Wo in welcher Klasse und Methode kann der Teilnehmer was in die DB Schreiben?Wie ist das hast nur du die App auf dem Handy und bedienst die auch wehrend einer Regatta oder können die Teilnehmer das auch zwischendurch machen?
Oder können die Teilnehmer zwischendurch nur lesen? Wenn Ja welche Klasse Methode.
Zurück zu dem Thema von gestern. Für mich ist das zeitlich nicht ganz richtig.
Du hast deine Liste die du in der for Schleife durchgehst. Für jedes Element erstellst du einen Eventlistner.
Aber nur wenn sich auch etwas etwas in den Daten verändert hat wird er aufgerufen wann das ist unklar. Mit Sicherheit nicht wenn deine for schleife läuft. Und nur wenn du in dem Listner bist können auch daten in die Db geschrieben werde. So ist zumindest dein Code.
Ich die Erstellten Eventlistern sind auch noch nach dem durchlauf der For schleife aktiv und reagieren alle unabhängig von einander auf Veränderung der Daten auf die sie sich beziehen.
Erst wenn die Avtivityverlassen wird werden die Listner wahrscheinlich beendet.
Wer kann den die Methode Zeitberechnung auslösen.? Wie oft wird das gemacht?
Bemerken möchte ich noch auch wenn der Teilnehmer gestoppt wurde läuft der Eventlistern weiter und führt seinem Code aus.
Der Listner ist nach dem ersten Aufruf immer aktiv. Kommt zu ihm ein Event weil sich daten geändert haben wird der code ausgeführt und eventuell auch etwas in die DB gespeichert.
Für mich ist hier ein Logik Fehler.
Wenn ein Teilnehmer gestoppt wird finde ich nichts was den Eventlistner löscht. Oder das der Listner weis das gestoppt wurde und er nichts mehr zu tun hat wenn noch ein Event kommt. -
Die Drawable habe ich gelöscht weil sie Daten von Vereinsmitgliedern enthalten. Sorry xD
Ja, nur der Admin bzw der schiedsrichter in dem fall soll die zeit stoppen können. Das machen wir indem der normale Benutzer auf der Startseite garnicht den Button angezeigt bekommt um diese "Regatta", so nennt sich das, zu starten.Der Teil wo die Daten gespeichert werden habe ich oben geschickt.
Es gibt die Klasse Regatta in der Quasi alles wesentliche gemacht wird. Auch die Daten übertragen zu verrechnen etc.
Dann gibt es dort noch eine Klasse welche für die anzeige der einzelnen Benutzer zuständig ist. Da wird dann z.b. die zeit gestoppt und die gestoppte zeit dann in eine map von der Klasse Regatta gespeichert, in "userLastTime".Die Punkte werden in der Klasse Regatta, in der Methode Zeitberechnung übertragen. Wie meinst du genau wo wo er das macht...? Er klickt auf den finsih button, der onClickListener löst aus und startet die methode "rundenAnzahlBerechnung". Hier wird geschaut in welcher runde alle teilnehmer sind und welches die niedrigste runde ist. diese wird dann gewertet. sobald die niedrigste runde berechnet wurde startet sich die methode "displayConfirmView". Hier wird einfach nur angezeigt das z.b. die zweite runde gewertet wird. und ob das so richtig ist. sobald man auf ja drückt startet sich "zeitBerechnung". Hier werden erstmal die Zeiten der Teilnehmer aus der jeweiligen runde in die Map "zeitTabelle" gespeichert. Diese wird dann sortiert. Also wer ist als erste ins ziel gekommen. Dann wird die Zeit mithilfe eines Yardsticks (das ist dieser Persönliche wert) umgerechnet. Wer jetzt erster ist bekommt einen punkt. wer zweiter ist 3. Der dritte 5.7 usw. Diese Punkte werden in die Map "alleUser" gespeichert. Diese Map enthält alle Benutzer, am anfang mit 99 Punkten. Jeder der nicht Teilgenommen hat bekommt nämlich 99 Punkte. Jetzt wird in der zeitberechnungsmethode für alle teilgenommenen eine punktzahl errechnet welche die 99 Punkte einfach überschreibt.
Dann wird egal ob es eine Regatta oder ein neuer lauf ist (einfach nur eine andere struktur zum abspeichern) die map alleuser komplett durchlaufen und mithilfe vonJavamDatabase.child("regatten").child(Integer.toString(regatten+1)).child("1").child(key).setValue(alleUser.get(key));
übertragen.
Wie gesagt darf das nur der Admin (schiedsrichter) machen. Alle normalen Benutzer können nichts in die datenbank schreiben. Sie können nur lesen. Also um z.b. auf der startseite ihre gesammtplatzierung zu sehen. Später dann auch einzelte bewertungen der jeweiligen läufe und regatten (deshalb die unterteilung beim abspeichern).
Wie du vielleicht schon rausgelesen hast ist das eine app für einen Segelverein. Der Schiedsrichter sitzt am rand und schaut den teilnehmern zu bzw stoppt ihre zeiten. Die Teilnehmer selbst können erst nachdem es gewertet wurde auf der startseite die gesammt plazierung sehen.
Den rest vom Text muss ich erstmal noch kurz verstehen xD -
Wie gesagt ist das meine erste App, daher will ich nicht verwerfen das es Logig fehler gibt. Allerdings versteh ich gerade nicht über welchen Eventlistner du redest. Wo meinst du den wird er aufgerufen?
Java
Alles anzeigen//Bei Neuer Lauf else if(auswahl.equals("Neuer Lauf")){ mDatabase.child("regatten").child(Integer.toString(regatten)).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { lauf = 0; Iterator<DataSnapshot> dataSnapshots = dataSnapshot.getChildren().iterator(); while (dataSnapshots.hasNext()) { DataSnapshot dataSnapshotChild = dataSnapshots.next(); lauf++; } for (String key : alleUser.keySet()) { mDatabase.child("regatten").child(Integer.toString(regatten)).child(Integer.toString(lauf+1)).child(key).setValue(alleUser.get(key)); } regattaAbbrechen(); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); }
Meinst du hier? Das ist soweit ich rausgefunden hatte meine einige Möglichkeit die Datenbank auszulesen.. In dem fall will ich übrigens rausfinden wie viele läufe schon existieren. Also wenn es 4 läufe gibt soll der nächste als lauf 5 gespeichert werden.
-
So ich noch mal
Wo genau bei was ist dein Problem? Beschreibe das genau.
Ich gehe doch wohl richtig in der Annahme das mit dieser Zeile in dem Eventlistner etwas in die Db geschrieben wird.
mDatabase.child("regatten").child(Integer.toString(regatten)).child(Integer.toString(lauf+1)).child(key).setValue(alleUser.get(key));
„setValue“ schreib nach meiner Auffassung auch in die DB.
Und das in dem EventListner finde ich merkwürdig.
Stoppen … tust du in einen Clicklistner und in dem ViewHolder Methode willst du speichern.
Nur ersten wo wird die ID gesetzt?
Wo ist da der Bezug zurDB zum speichern in der Methode ÜbertrageDaten?
Das wird bestimmt nicht in der Db ankommen .
Auch komisch ist das du das put schonindem OnClicklistner machst und dann nochmal die ÜbertrageDten Methode aufrufst.
Zb Regatta.userLastTime.put(viewHolder.id, viewHolder.lastTime);
viewHolder.übertrageDaten(); Für mich speicherst du garnichts in die DB kann kein Pusch, setValue und auch keine Ref auf die DB erkennen. So wie dein Code jetzt ist speicherst du nur in den Eventlistnern. Woanders nicht.Und das ist total falsch wird nie hundertprozentig gehen. Wenn du den Button stopp drückst solltest du auch das gleich in die DB speichern. Und nicht erst wenn ein Event Eintritt wenn überhaupt eines kommt. -
das ist der eventlistner von den wier reden
mDatabase.child("users").child(e.getKey().toString()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override........wo anders findet kein speichen in die Db stat.
-
Hier siehst du wie es in der datenbank gespeichert wird. Regatta eins und zwei sind fehlerhaft. bei Regatta 3 hat es wieder geklappt.
Du kannst dich auch gerne mal einloggen. Und es selbst Probieren.
Du hast allerdings leider nicht die möglichkeit dir die datenbank selbst anzeigen zu lassen. Allerdings wird auf der Startseite ja die gesammt Plazierung angezeigt. Daraus kann man es sich ja herleiten. erster Platz 1 punkt, 2 Platz 3 Punkte, 3 Platz 5,7 Punkte. Wenn ein Teilnehmer nicht teilgenommen hat erhält er 99 Punkte. Auf der startseite werden die 99 punkte nicht angezeigt das hat den grund das dort geschaut wird wie viel spiele es insgesammt gab z.b. zwei stück. Hat ein Teilnehmer zweimal gefehlt hat er natürlich 198 Punkte. Also werden bei zwei spielen gesammt alle teilnehmer mit 198 Punkten nicht angezeigt. Bei vier spielen dann alle mit 396 Punkten usw. -
Code
Alles anzeigenlass ViewHolder{ TextView name, time, rundeTV; Button btnStop, btnClear, btnRundeEntfernen, btnRundeHinzufügen; //Ist der Spieler editierbar (Wurde die Zeit schon für den Spieler gestoppt?) Boolean editable = true; //ID des Spielers String id; //Die gespeicherten Runden Zeiten List<String> lastTime = new ArrayList<>(); //die momentan angezeigte Runde int runde = 1; //Wie oft wurde zurückgedrückt (welche Runde wird momentan angezeigt) int zurückGedrückt = 0; public void übertrageDaten(){ Regatta.isUserEditable.put(id, editable); Regatta.runde.put(id, runde); Regatta.zurückgedrückt.put(id, zurückGedrückt); Regatta.userLastTime.put(id, lastTime); } }
hier wird nichts an die db übertagen .
-
ich glaube du hast das Prinzip der Db noch nicht verstanden wie gespeichert und wie etwas gelesen werden kann. das ist eine Realtime Db die das lesen über listner macht. Schreiben direckt. Ohne Listner.
Schreibst du in einem Listner schreibt er nur wenn du auch im listner bist also die daten verändert oder du neu die daten lesen muss weil du vorher auf einer anderen Activity warst. -
bei keinen deiner klicks wird etwas sofort an die dB geschikt.
Wieso musst du in dem ich sage mal anzeige listner der dir die daten hollt und anzeigt . ausch scheiben. Ist total falsch wird nie sinnvol laufen. Wenn sich du klickst musst du selber die DB schreiben und das nicht den anzeigelister Überlassen.
Auch solltest du zu diesen Zeitpunkt die punkte Zeiten usw berechnen und in der Db mitspeichert . dann sind sie auch zeitgleich beim
Teilnemer. Der brauch dann auch nichts berechnen.
So zu deiner App welche Klasse und Layout sieht den der Teilnehmer?
-
Etwas schwer zu erklären und warscheinlich auch umständlich gelöst xD.
In dem viewHolder gibt es zwar die methode übertrageDaten(), allerdings überträgt die mir die daten nicht in die datenbank sondern in meine Klasse Regatta.
Das hat den Grund das es die funktion gibt teilnehmer hinzuzufügen bzw mitspielen zu lassen nachdem die ersten schon gestoppt wurden.
Hätte ich jetzt alles nur in meinem Viewholder gespeichert und füge einen neuen Spieler dazu wird ja sozusagen eine Neue Liste gemacht, also alle daten wären.. weg? überschieben? auf jedenfall hatte ich dann keinen zugriff mehr. Das habe ich gelöst indem ich die Daten zwar in den Viewholder speichere allerding zusätzlich immer in meine Regatta Klasse. Somit kann ich später einfach fragen ob für den Teilnehmer schon daten existieren und sie wieder in den viewholder neu reinspeichern.Ja, mit der Zeile wird geschrieben.
Das findet in dem Eventlistener statt weil ich erst rausfinden muss wie viele Läufe schon existieren um es auch richtig zu speichern.
Der Grund weshalb ich es innerhalb des Listeners mache ist weil ich schonmal das Problem hat das das ganze Asynchron läuft. Hätte ich beispielsweiße die zeile zum übertragen auserhalb meines Listeners, dann versucht das Programm erst die Daten zu übertragen und startet danach erst den Listener... Was ja völliger schwachsinn ist da ich ja erst rausfinden muss wie viel vorherige läufe es gibt.Das kann allerdings nicht unsere Fehler ursache sein. Wir haben ja zwei arten es zu speichern. Einmal als lauf und einmal als regatta. Bei Regatta Option findet das ganze ohne den EventListner statt. Trotzdem funktioniert die übertragung (siehe foto) nur manchmal
-
Zitat
In dem viewHolder gibt es zwar die methode übertrageDaten(), allerdings überträgt die mir die daten nicht in die datenbank sondern in meine Klasse Regatta.
und das ist flasch wird nie etwas werden auf diese art.
Überlege dir ein sinnvolles ordentliches Prinzip das wird nie nichtig laufen
ZitatBei Regatta Option findet das ganze ohne den EventListner statt. Trotzdem funktioniert die übertragung
wo ist das?
wenn ich in deiner Kalsse Regatta mir deine Ref mDatabase suche ist die Immer in einem Listner.
-
1. Es soll ja auch nie was sofort in die DB geschickt werden. Erst sobald er fertig Klickt also alle Teilnehmer im Ziel angekommen sind, kann ja auch berechnet werden.
2. wenn ich es auserhalb des Listeners übertrage hab ich nunmal das Problem der Asynchronität bei der ich mir anderst nicht zu helfen weiß.
3. Was ist an dem übertrageDaten() falsch? unsauber ja aber wieso falsch? bei jeder veränderung im viewholder übertrage ich meine daten in maps meiner regatta klasse. und aus diesen maps berechne ich ja meine Punktzahl.Wieso funktioniert es dann als wenn der Debugger läuft? Man merkt ich bin gerade etwas überfordert und versuch es zu verstehen
-
weil die daten nur übertragen werden wenn der listner aufgerufen wird. und wenn du klickst wir er ganz bestimmt nicht von der DB aufgerufen den der Inhalt des Child auf das er schaut hat sich nicht geändert.
Schaue dir an wann und zu welchen Zeitpunkt du in die onDataChange Methode des jeweiligen Teilnehmer kommst. Denn listner gibt es so oft wie Teilnehmer.Und nur wenn du in dieser Methode bist speichert du was in die db sonst nicht. die daten sind zwar lokal gespeichert in den Variablen der ViewHolder Klasse (die git es auch so oft wie Teilnehmer) aber nicht in der db.Ich verstehe nicht warum du das speicher nicht im Viewholder machen kansst. Du hast ad alle daten des Teilnehmer wenn nicht frage sie aus der Db ab.Dann sind die daten auch sofort nach dem klick aktuell und nicht irgend wann. Wann das ist kannst du nicht bestimmen.
-
wo ist das?
wenn ich in deiner Kalsse Regatta mir deine Ref mDatabase suche ist die Immer in einem Listner.
Ups ich hatte übersehen das
Java//bei neue Regatta if(auswahl.equals("Neue Regatta")){ for (String key : alleUser.keySet()) { mDatabase.child("regatten").child(Integer.toString(regatten+1)).child("1").child(key).setValue(alleUser.get(key)); } regattaAbbrechen(); }
auch in dem Listener drin ist welcher mir den Yardstick ausliest.
Aber wie bekomme ich das ganze dann auserhalb des Listeners ohne das es Asynchron läuft? Hab da nunmal das problem das der code einfach weiterläuft ohne zuerst sich die daten aus der datenbank zu holen O.o
-
Das ganze geht einigermaßenweil du beim speichern alleUser in einer For schleife speicherst.
Aber genau das solltest du nicht in der View holder klasse machen und da genau nur den einen aktuellen User.
Eigentlich solltest du die daten in der DB nicht speichern sondern Updaten wiedas jetzt in der Firebase db geht muss ich erst nach schauen mache ich zu wenig.
Aber wenn du nur den einen User neu speicherst sollte das auch gehen.
Beieiner SQL gibt es insert und ubdate wie es hier ist Weiß ich jetzt nicht im Moment
Für mich macht es auch keinen sinn immer alle user neu zu schreiben in dem Eventlistner.
Denn nur dadurch geht es bedingt.
Wenn du die daten des einzeln User Updates oder auch neu schreist in deiner ViewHoder Klasse werde sie auch anschießend ordentlich angezeigt weil nach den schreiben wird auch der Lissner des Users aufgerufen und zeigt an. -
userRef.child('mike').update({'dateOfBirth': moment(value.dateOfBirth).toDate().getTime()})https://medium.com/@hasangi/wr…h-javascript-f26113ec8c93
-
Okay das wird ja leider doch komplizierter als erhofft...
Könntest du das mit dem Speichern und updaten kurz nochmal erläutern?
Ich versteh gerade nicht warum ein Update mir helfen kann. Ich bin absoluter Neuling der versucht sich so gut es geht alles selbst beizubringen und froh das der code bis dahin einigermasen funktioniert hat.Updaten macht in meinen augen ja nur dann sinn wenn sich z.b. nur ein wert ändert oder? In meinem Fall füge ich doch einmal komplett neue werte in meine Datenbank ein. Sei es bei einer Regatta oder einem Lauf.
Für mich macht es auch keinen sinn immer alle user neu zu schreiben in dem Eventlistner.
Ich muss sie doch allerdings neu schreiben... Bis sie geschrieben worden sind existieren sie ja garnicht in der Datenbank.
Wenn du die daten des einzeln User Updates oder auch neu schreist in deiner ViewHoder Klasse ...
Die Daten aus dem Viewholder haben ja an sich noch garnichts mit der datenbank zu tun... Im Viewholder wird ja nur gespeichert Teilnehmer sowieso hat in runde eins 5 minuten gebraucht, in runde 2 so und so lange etc.. Heißt ich muss am ende ja immernoch erstmal mir die Zeiten von allen benutzern aus der jeweiligen runde holen um überhaupt auszurechnen wie viel Punkte er bekommt. also mit wie vielen Punkten ich ihn erst in die datenbank schreibe.
-
Zitat
Ich muss sie doch allerdings neu schreiben... Bis sie geschrieben worden sind existieren sie ja garnicht in der Datenbank.
Genau das ist das Problem.
endlich hast du es erkannt.Da du alle User speichert geht das manchmal um genau zu sein werden die date in einen nicht zu dem user gehörenden Lister mit gespeichert gespeichert. Denn das speichern aller User machst du ja in allen listnern, die in der ersten for schleife erstellt werden.
Wird kein listender aufgerufene geht gar nichts.
Du musst die daten in die db speichern wenn sie entstehen also wenn du auf stopp drückst. In diesem klicklistner rufst du die speichermetrote der ViewHolder Klasse auf. Soweit richtig. Aber jetzt musst du genau den einen DatenSatz auch speichern. Oder wenn er schon existiert updaten.
Das speichern aktualisieren in der Eventlistnern der zeitBerechnungs Methode wird immer zu felern führen und solltest du nicht machen. Glaube mir und versuche es anders. Wenn du es schon nicht verstehen willst mach es einfach. -
Hallo habe es eben mit deinen Zugangs daten mal etwas durchgespielt.
Wie ich mir dachte wird wenn ich eine neue Regatta mache user auswähle und dann auf Start drücke deine Methode zeitberechnen nicht aufgerufen. Es gibt auch nur einen Aufruf der Methode in deinem Code. Zeile 195
Somit wird gar nichts in die DB geschrieben .
Eigentlich sinnlos so etwas.
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!