Probleme mit Spinnern und deren Adapter

  • Moin,


    habe aktuell Probleme damit, den verschiedenen Spinnern in meiner App die Adapter zuzuteilen und diese dann in den Shared Preferences zu speichern.
    Bei der Zuteilung der ArrayAdapter habe ich immer die von Android Studio vorgeschlagenen genutzt, also set Adapter, adapter1, adapter2, etc.
    Beim Versuch, die eingegebenen Daten der Spinner nun zu speichern, wird lediglich einer beim holen der Daten über die Retrieve Methode wiederhergestellt, und nicht wie gewünscht alle.


    Ich glaube ich habe auch schon viele Varianten probiert, aber nichts half. Ebenso war es im Netz schwierig, etwas Vergleichbares zu finden...



    Nachtrag: Habe mal in der Shared Preferences Datei nachgesehen: Fülle ich nur die Spinner mit Werten (Alter, Geschlecht, Dauer), so spuckt die Datei lediglich Männlich Männlich Männlich aus. Also muss ja irgendwas mit den Arrays und Adapte-Zuteilung nicht hinhauen...


    Hier ist mal der Code:




  • [code=java] public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    Alter = parent.getItemAtPosition(position).toString();
    Geschlecht = parent.getItemAtPosition(position).toString();
    Dauer = parent.getItemAtPosition(position).toString();
    }[/quote]Hier setzt Du alle drei Werte auf denselben Wert.
    Welchen Spinner Du auch immer anwählst, alle drei Variablen haben dann den gleichen Inhalt, zum Beispiel 'männlich'.


    Du trägst also einfach für jeden Spinner einen eigenen, anderen OnItemSelected Listener ein oder machst bei Deinem generischen Listener eine Unterscheidung nach dem Spinner.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Danke dir für den entscheidenen Tipp! Habe jetzt OnItemSelected Listener auf jeden Spinner angesetzt, sieht schlimm aus, geht aber und das zählt in dem Fall.


  • Neuer Tag, neues Problem. Wie gesagt speichert er jetzt brav die XML Datei in dem SharedPrefOrdner. Jetzt würde ich diese XML Datei sehr gerne in einer anderen Aktivität laden und irgendwie darstellen, z.B. in einer Tabelle, welche genau diese in der XML Datei angegegeben Kriterien abbildet?
    Geht das ganze überhaupt über SharedPref oder muss ich auf Internal oder External Storage umschwanken?

  • Generell: So ähnlich wie Du die Daten schreibst, liest Du sie auch wieder aus.
    Also statt '.putString(key, value)' auf dem Editor ein '.getString(key)' direkt auf die SharedPreferences.


    Aber: In die SharedPreferences gehören nur Benutzereinstellungen, die über Deine App geteilt werden.
    Daher auch der Name.
    Alter und Geschlecht sind da durchaus speicherwürdige Einstellungen (Wobei ich 'Geburtsdatum' dem 'Alter' vorziehen würde. Letzteres ändert sich jährlich, ersteres eigentlich nie.)


    Startpunkt, Dauer, Geschwindigkeit, Streckenprofil und Distanz dürften sich bei jedem Lauf (oder was auch immer Du da aufzeichnen möchtest) ändern.
    Vermutlich möchtest Du eine Liste vorhalten, in der man sich die Daten jedes einzelnen Laufs ansehen kann.


    Dann solltest Du diese Informationen unbedingt außerhalb der SharedPreferences in einer eigenen SQLite Datenbank aufbewahren :)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Hallo Marco,


    danke schonmal für deine Hilfe. Wie du fast richtig erkannt hast, geht es im Grunde darum, eine Aktivität zu erstellen, an welcher andere Sportler teilnehmen können. Deswegen soll an der einen Stelle die Aktivität definiert nach Kriterien gespeichert werden und an einer anderen Stelle dann geladen werden, nämlich dort, wo andere Sportler teilnehmen können.
    Eigentlich müsste das ganze logischerweise über einen Server laufen, sonst wäre es ja Quark, aber da mir die Zeit und Mittel fehlen, um mich da noch einzulesen, wollte ich lediglich kurz simulieren, dass das ganze über einen Server läuft.
    Deswegen soll das ganze auch erstmal in der App bleiben und somit nur von der einen in die andere Aktivität wandern.


    Aber irgendwie ahne ich schon, dass ich da wohl oder übel was ändern muss...

  • Also wenn Du auch noch mehrere unterschiedliche Sportler vorhalten möchtest, sind die SharedPreferences definitiv der falsche Ort.


    Am Besten realisierst Du die Lösung in SQLite mit den entsprechenden Konzepten.
    Das Tutorial Android SQLite database and content provider von Lars Vogel ist da ein prima Einstieg.


    Wenn Du Dich da durchgearbeitet hast, ist das schon mal ganz prima und es sollten sich viele Fragen erledigt haben.


    Vor Allem: Wenn Du einen Content Provider nutzt, ist es ein Leichtes, den gegen einen Content Provider mit Serverzugriff auszutauschen.
    Du kannst auch einen hybriden Content Provider bauen, der erst mal lokal arbeitet und dann mit dem Server kommuniziert – alles ohne Deine funktionierende Demo App anpassen zu müssen.
    (Das sind dann aber schon advanced topics +g+)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

    Einmal editiert, zuletzt von Marco Feltmann ()

  • Jip, habe ich jetzt auch geändert. Hatte mich schon vorher an eine andere Quelle für SQLite-Tutorials gehalten. Sieht auch insgesamt besser, auch das, was er am Ende ausspucken soll. Endlich mal eine Tabelle, yeah :D


    Ich habe jedoch einen Fehlen, zumindest spuckt mein LogCat dies aus: Er sagt Syntax Fehler in der nähe von Age.


    Ich vermute, dass ich irgendwie die Table falsch definiert habe und irgendwo ein Komma oder Leerzeichen zu viel/wenig gesetzt habe, was ja ein häufiger zu sein scheint.
    Habe schon ein wenig rumprobiert, aber gefunden habe ich leider noch nichts...


    Finde das immer ganz witzig, wenn man wenig Erfahrung und kaum Basics hat, muss man sich seine Happen immer zusammensuchen, diese kombinieren und ist damit Fehleranfällig. Fehler auszumerzen dauert dann gefühlt 1000 Jahre.
    Würde die Sache eigentlich anders angehen, da dies aber für ein Projekt mit Deadline in kürze ist, muss ich erstmal so weitermachen...


  • Problem gelöst, wie vermutet ein Leerzeichen oder Komma vergessen, für die Nachwelt:


  • Ich bin gerade dabei, die SQL Tabelle irgendwie in die andere Aktivität zu Laden. Über den Device Monitor und SQLite Browser habe ich die Tabelle bereits ausgelesen und soweit passt alles.So sieht es aus:



    Nun ist mein Plan, dass ich das ganze aus der Aktivität Cycling_Create über die Spinner und TextEdit Maske eingegeben wird und in der Aktivität Cycling_Join in der Form wie im SQLite Browser angezeigt, wieder ausgespuckt wird.
    Erstelle ich dann eine neue Aktivität, wird eine neue Zeile hinzugefügt usw.
    Rausgefunden habe ich bereits, dass es anscheinend zwei Ansätze gibt: ListView und TableLayout.


    Finde aber beide recht kompliziert, gibt es da nicht was einfacheres, welches sich immer automatisch die Daten aus der Database zieht?

  • Im verlinkten Tutorial wird ungefähr das gemacht, was Du möchtest.
    Halt mit der ListView.


    Wenn Du da lieber selbst auf alternativen Pfaden herumprobieren möchtest, dann kannst Du das gern tun.
    Allerdings werde ich Dir dann nicht weiter helfen können, da ich immer den erprobten Standardweg nehme.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Hi, ich wieder.


    Habe mich die letzten Tage nochmal dran gemacht und probiert das ganze zu implementieren, jedoch habe ich nicht nur das Tut. von Vogella genommen, sondern auch jenes: http://www.programmierenlernen…ben-und-lesen-in-android/


    Fangen wir mal mit dem DB Helper an:



    Wie auch bei Vogella habe ich als nächstes eine Data Klasse erstellt:



    Weiter geht es mit der Datasource:


  • Und jetzt wird es haarig. Da ich nicht nur eine Activity habe, welche sowohl die Eingabemaske als auch die Darstellung über ListView zeigt, wird es nun kompliziert.


    Meine Activity Cycling_Create ist das UI mit zwei TextEdit und sechs Spinner. Hier sollen die Daten in die Datenbank gespeichert werden.
    Die Activity Join soll am Ende die eingegebene Daten aus der SQL Base ziehen und als ListView ausspucken.


    Hier ist mal meine Cycling_Create:






    CyclingJoin hänge ich auch schonmal an, aber da ist noch nicht viel drin...




    Mein Hauptproblem ist derzeit noch beim Schreiben in die Datenbank, da beim Drücken des Create Button die App abstürzt.
    logcat sagt dazu das, womit ich jedoch nicht wirklich was anfangen soll. Das Internet sagt, dass irgendwas mit dem Cursor und der null nicht stimmt, aber da hört es schon auf bei mir. In die DB wird wie gesagt noch nichts geschrieben, erstellt wird sie aber...



    Code
    09-15 20:48:10.459 2027-2027/uni_hannover.sportapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: uni_hannover.sportapp, PID: 2027
    android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0


    Ich werde morgen nochmal mit Vollgas rangehen und mit dem Vogella-Link abgleichen und anpassen, aber vielleicht kann mir wer von euch auf die Schnelle schon bei diesem Fehler oder etwas grundsätzlich falschen behilflich sein?

  • Ich vermute an Hand der Quellen das Problem hier:

    Zitat

    cursor.moveToFirst();

    Leider sagt Dein LogCat Abschnitt nicht mehr aus.


    Deshalb vermute ich nur entweder in der createCyclingMemo() oder in der getAllCyclingMemos()
    Es ließt sich für mich so, als wolltest Du via cursor.moveToFirst(); das erste Element des Cursors abrufen, der exakt 0 Elemente hat.


    Werte mal den Rückgabeparameter der Funktion an beiden Stellen aus.
    Wenn da ein false zurück kommt, hat irgendwas nicht geklappt.
    Vermutlich willst Du die Daten lesen und es sind überhaupt keine da.


    Eventuell (ich kenne die Implementierung da nicht) kannst Du auch date('now') als Column eingeben.
    Das sollte zumindest immer den aktuellen Timestamp als Ergebnis zurückliefern.
    (Vielleicht musst Du das aber auch explizit über execSQL eingeben…)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Stimmt, du scheinst recht zu haben, ich hatte ja auch schon nachgesehen und nach der Eingabe von Daten war die SQL DB leer...somit probiere ich hier Daten auszulesen, welche nicht existieren.


    Meine neue Vermutung ist, dass der Fehler hier liegt, insbesondere habe ich Probleme damit, den Stringwert in Zeile 17 in eine Intwert umzuwandeln...
    Ich muss mal rausfinden, wie ich manuell Daten in die DB einfüge...


    Nachtrag: Mir fiel gerade auf, dass das ja quark ist, also habe ich "int NDA = Integer.parseInt(NDAString);" einfach rausgehauen.


    Nachtrag 2: Der Kollege schreibt wieder in die DB, d.h. es nass irgendwas anderes sein...



    Natürlich ist das ganze noch nicht fertig, wäre auch zu schön, neuer logcat:



    Code
    database.sqlite.SQLiteException: no such column: NDA (code 1): , while compiling: SELECT NDA, Startpunkt, Age, Geschlecht, Dauer, Geschwindigkeit, Streckenprofil, Distanz FROM cycling WHERE NDA=-1
  • Naja, hier ist er ganz eindeutig davon überzeugt, die Spalte NDA nicht zu kennen.


    Vielleicht solltest Du die hart codierten Spaltennamen durch Deine Vorlagen wie CyclingMemoDBHelper.COLUMN_NDA ersetzen.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • In der Datasource hast Du folgendes definiert:

    Java
    private String[] columns = {
                CyclingMemoDBHelper.COLUMN_NDA,
                CyclingMemoDBHelper.COLUMN_Startpunkt,
                CyclingMemoDBHelper.COLUMN_Age,
                CyclingMemoDBHelper.COLUMN_Geschlecht,
                CyclingMemoDBHelper.COLUMN_Dauer,
                CyclingMemoDBHelper.COLUMN_Geschwindigkeit,
                CyclingMemoDBHelper.COLUMN_Streckenprofil,
                CyclingMemoDBHelper.COLUMN_Distanz
        };


    Ich hatte eigentlich gedacht, Du tippst die Tutorials ab und versuchst sie zu verstehen anstatt das einfach reinzukopieren.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Keine Frage, ich probiere so viel es geht zu lernen und auch zu verstehen, nur muss ich in der kurzen Zeit abstriche machen. Also wenn ich bei einem Begriff wie Hardcoded String und eNum to String Methode nicht gleich aufspringen kann, seht mir das bitte nicht nach...


    Das Problem habe ich mittlerweile (bzw. gerade eben) lösen können. Habe gerade mit dem Dokumentieren begonnen, bin alles nochmal durchgegangen und habe probiert nochmal alles "abzugehen" und dabei muss ich wohl den entscheidenen Fehler rausgehauen haben.


    Danke euch!

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!