Android Studio Datenbank Einstieg

M

Menten

Neues Mitglied
0
Hallo zusammen,

ich versuche gerade mich mit dem Buch "Adroid-Apps programmieren" von Eugen Richter in die Android Entwicklung mit dem Adroid Studio einzuarbeiten. Leider bin ich jetzt an einen Punkt gekommen, wo mir das Buch nicht weiter hilft.

In dem Buch wird eine Zeiterfassung mit einer SqLite Datenbank entwickelt. Nach der Erfassung sollen die Werte dann in einer Liste angezeigt werden. Wenn ich aber die Liste anzeige, wird bei mir immer nur der erste Eintrag angezeigt. Ich habe meine Quelltexte mit den Beispielquellen des Buches verglichen, finde aber keinen Unterschied. Auch auf Groß/Kleinschreibung habe ich geachtet.

Wenn ich die Beispielquellen laufen lassen, funktioniert das Ganze.

Hat jemand eine Idee woran das liegen könnte?

Danke und
Viele Grüße
Stefan Menten
 
Hallo und Willkommen im Forum.

Schwierig zu beantworten ohne Code.
 
Ich habe das komplette Projekt mal angehängt.
 

Anhänge

  • Zeiterfassung.zip
    20,8 MB · Aufrufe: 89
Hallo

Ich würde sagen es liegt and dem „LoaderManager“ in der ListDataActivity der ist seit API 28 deprecated.
https://developer.android.com/reference/android/app/LoaderManager
Das setzt die Support Library voraus du benutzt aber androidX.

Schaue mal bei den Beispiel Projekten aus dem Buch die Galle Files an.

Ich denke das in dem Buch noch die Support Library benutzt werden.
Und compileSdkVersion unter 28 ist
Auch targetSdkVersion wird unter 28 sein
 
Hallo,

Danke erst mal für die Hilfe.

Das mit der Version hab ich mir auch schon gedacht. Die Imports im Beispielcode verwendet tatsächlich Support.v4 bzw. v7. Wobei ich allerdings nicht weiß wie ich das würde konfigurieren können.

Ich habe jetzt das "getSupportLoaderManager" mal gegen "LoaderManager.getInstance(this).initLoader(_LOADER_ID, null, this);" (Bzw. destroyLoader) ausgetauscht. Damit bekomme ich aber auch nur die erste Zeile in der Datenbank angezeigt.


Danke und Gruß
Stefan Menten
 
Hallo
Mir ist in deinem Code noch etwas aufgefallen.

In der Activity ListDataActivty erstellst du ein Objekt von TimeDataAdapter was deine Liste RecyclerView ist. Speicherst das in der Variablen _adapter.

Nur müsstest du dort so wie ich den Code verstehe auch den Cursor mit den Daten aus der DB Übergeben und nicht Null.

_adapter = new TimeDataAdapter(this, null);
public TimeDataAdapter(Context context, Cursor data) {…..

Ist das in dem Buch Beispiel auch so?


Außerdem denke ich das die Klasse "TimeDataContract" auch "static" sein müsste damit du auch ohne Instanz auf die vielen Statischen Variablen zugreifen kannst.

PS. auch Cursoloder womit du versuchst Daten aus den ContentProvider zulesen ist seit API 28 deprecated.
 
Zuletzt bearbeitet:
Hallo,
so wie ich das verstehe passiert die Übergabe der Daten hier:

Java:
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
        int cnt = data.getCount();

        switch (loader.getId()) {
            case _LOADER_ID:
                _adapter.swapCursor(data);
                break;
        }
    }

Da habe ich die Anzahlsätze mal abgefragt und bekomme da auch die richtige Anzahl.

in swapCursor werden die Daten dann an den Adapter übergeben:
Java:
    public void swapCursor(Cursor newData) {
        if (_data != null) {
            // Cursor schließen
            _data.close();
        }

        _data = newData;
        notifyDataSetChanged();
    }

Ich habe mal das Beispiel-Projekt angehängt.

Bei dem " TimeDataContract" gab es einen Unterschied. Die ist im Beispiel "final". Änderung hat aber auch nichts gebracht.

Kann es sein, dass das Problem auch mit dem RecyclerView zusammen hängt? Weil der nur eine Zeile anzeigt oder so? Ich habe gerade mal in dem CursorLoader die Sortierung umgekehrt. Damit bekomme ich dann den letzten Datensatz angezeigt.


Danke und Gruß
Stefan Menten
 

Anhänge

  • 11_loader.zip
    9,6 MB · Aufrufe: 36
Ich würde es wirklich mit den Support libs Probieren.
Beim erstellen eines neuen Projektes kannst du ja auswählen das du mit den Support libs arbeiten willst.
Beiträge automatisch zusammengeführt:

hier fehlt ein punkt
manifest original
<provider
android:authorities="de.webducer.androidbuch.zeiterfassung.provider"
android:name=".db.TimeDataProvider" />

deines

<provider
android:authorities="de.menten.zeiterfassung.provider"
android:name="db.TimeDataProvider"
/>


Edit der Punkt alleine ist es nicht.
Du musst dein Projekt Datei Struktur auch anpassen sowie die Paketnamen der Adapter und Hilfsklassem.
Schaue dir dein Original an.
 
Zuletzt bearbeitet:
Hallo,

du meintest, dass die Packages "db" und "adapter" nach "zeiterfassung" verschoben werden müssen wenn ich das richtig verstehe? Hab ich gemacht. Ist aber immer noch das selbe Problem.

Ich habe jetzt mal debugged was da passiert. Im LinearLayoutManager werden in der Routine "Fill" views für jeden Eintrag erzeugt.

Für jeden Eintrag wird in Fill die Routine "layoutChunk" ausgerufen und darin ein "Consumed" Wert für den Eintrag ermittelt:

Code:
result.mConsumed = mOrientationHelper.getDecoratedMeasurement(view);

Dieses "getDecoratedMeasurement" liefert einen Wert der größer ist als der verfügbare Platz und dadurch wird dann in Fill nach dem ersten Eintrag abgebrochen.

Kann das an irgendeiner Einstellung liegen?

Danke und Gruß
Stefan Menten
 
Hallo
Ob es Das ist was du sagst?

Ich würde sagen das das notifyDataSetChanged() nicht richtig arbeitet. Es wird zwar nach dem swapCursor dein Cursor richtig in deine Klassenvariable gespeichert. Aber die onBindViewHolder Methode wird trotzdem nur einmal aufgerufen. Warum das datachanged nicht richtig geht kann ich dir nicht sagen.

Vielleicht solltest du dich für eine andere Update Variante entscheiden.
notifyDataSetChanged


public final void notifyDataSetChanged ()
Notify any registered observers that the data set has changed.

There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred. Structural changes are when items are inserted, removed or moved within the data set.

This event does not specify what about the data set has changed, forcing any observers to assume that all existing items and structure may no longer be valid. LayoutManagers will be forced to fully rebind and relayout all visible views.

RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have stable IDs when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.

If you are writing an adapter it will always be more efficient to use the more specific change events if you can. Rely on notifyDataSetChanged() as a last resort.
 
Zuletzt bearbeitet:
PS ich habe nur die Anzahl der cursor Einträge geprüft nicht die Richtigkeit der Daten die der Provider liefert.

Tipp migriere doch mal das original Projekt zu AndroidX und schaue ob es dann noch geht und wenn ja was alles gemacht wurde.
Das original arbeitet auch noch unter API 28 du unter 30.

Auch könntest du gleich beim ersten Aufruf des Recycler die Daten übergeben und nicht erst später in der swapCursor Methode.
 
Zuletzt bearbeitet:
Ich habe notifyDatasetChanged mal gegen notifyItemChanged ausgetauscht. Dann wird aber garnichts mehr angezeigt. Wundert micht auch nicht weil ich da eine Datensatznummer angeben muss.

Nachdem was ich bisher gesehen habe, werden die Daten aber auch richtig gelesen. In der Fill Methode des LinearLayoutManager kommt die Anzahl der gelesenen Sätze an.

Das Problem scheint mir in der weiteren Verarbeitung im RecyclerView zu liegen. Der einzelne View liefert eine Höhe von 888 Pixeln was natürlich dafür sorgt, dass nur für eine Zeile Platz ist.

Java:
    /**
     * Like {@link #getMeasuredHeightAndState()}, but only returns the
     * raw height component (that is the result is masked by
     * {@link #MEASURED_SIZE_MASK}).
     *
     * @return The raw measured height of this view.
     */
    public final int getMeasuredHeight() {
        return mMeasuredHeight & MEASURED_SIZE_MASK;
    }

Die swapCursor kommt aus dem Adapter. Der Adapter wird dem View zugeordnet. Der Loader füllt den Adapter mit den Daten worauf der Adapter seinen View informiert. Das ist doch auch so weil die Activity den Loader implementiert. Oder verstehe ich das falsch?
 
Ich hab jetzt das original Projekt auf AndroidX umgestellt. Und das funktioniert danach immer noch.

Was mir an meiner Version noch aufgefallen ist. Ich kann mit dem Scrollrad in den Einträgen scrollen, was aber schwer zu erkennen ist weil die Einträge ja 888 pixel hoch sind.
 
Hallo

Schaue dir mal die Layout Datei „item_time_data.xml“ genauer an.

Deine
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:weightSum="2">


Original

Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="2">


android:layout_height="wrap_content"
 
Verdampt, die Datei habe die ganze Zeit irgendwie übersehen! Das war's natürlich.

Danke für deine Hilfe!


Stefan
 

Ähnliche Themen

5
Antworten
0
Aufrufe
1.143
586920
5
SaniMatthias
Antworten
19
Aufrufe
947
swa00
swa00
D
Antworten
23
Aufrufe
2.527
Data2006
D
Zurück
Oben Unten