C, U und D fehlen bisher noch, here sind sie also.
Was wir noch machen müssen ist, zwei OnClickListener zu unseren Buttons (zum Daten Schreiben und Löschen) hinzuzufügen. Da ihr euch mittlerweile schon durch 3 Teile durchgearbeitet habt, wisst ihr bestimmt schon wie das geht. onCreate unserer LeaseActivity sollte so aussehen:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_lease); editTextItem = (EditText) findViewById(R.id.activity_lease_item); editTextComment = (EditText) findViewById(R.id.activity_lease_comment); spinnerPerson = (Spinner) findViewById(R.id.activity_lease_person); buttonSave = (Button) findViewById(R.id.activity_lease_save); buttonDelete = (Button) findViewById(R.id.activity_lease_delete); Intent intent = getIntent(); Long leaseId = intent.getLongExtra("lease_id", 0); if(leaseId != 0 ) { DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); LeaseDao leaseDao = daoSession.getLeaseDao(); lease = leaseDao.load(leaseId); if(lease != null) { editTextItem.setText(lease.getItem()); editTextComment.setText(lease.getComment()); } } buttonSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { lease.setItem(String.valueOf(editTextItem.getText())); lease.setComment(String.valueOf(editTextComment.getText())); DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); daoSession.insertOrReplace(lease); finish(); } }); buttonDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); daoSession.delete(lease); finish(); } }); }
Wie ihr seht, nehmen wir die Daten unserer EditTexts und schieben sie in die Objekte unseres Modells. Danach rufen wir eine von zwei Methoden auf (delete() oder insertOrUpdate() ), die alles Weitere übernehmen. Das war es schon, wieder kein SQL!
Wenn ihr die App jetzt startet, dann probiert Folgendes aus:
Öffnet ein Element in eurem RecyclerView und ändert Daten. Wenn ihr den „speichern“-Button drückt und das Element wieder öffnet, dann sind alle Daten wie erwartet sichtbar, unsere Daten sind also gespeichert. Wenn wir allerdings ein Element löschen, dann verschwindet es nicht aus dem RecyclerView.
Was läuft da denn falsch? Löschen geht nicht? – Doch, löschen geht, ABER der RecyclerView wird nicht benachrichtigt, dass sich der Datensatz geändert hat. Wir müssen also einen Weg finden, wie der RecyclerView eben diese Nachricht bekommt.
Normalerweise würden wir uns jetzt wieder mit Android Lifecyclemethoden beschäftigen, da unser Thema hier aber GreenDao ist, werden wir uns einfach mal über guten Stil hinwegsetzen und folgendes tun: wir überschreiben onResume(ihr wisst schon, Rechtsklick –> generate –> wählt die onResume-Methode aus) und gebt den folgenden Codeabschnitt ein:
DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); LeaseDao leaseDao = daoSession.getLeaseDao(); List<Lease> leaseList = leaseDao.loadAll(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.main_activity_recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); MainActivityListAdapter adapter = new MainActivityListAdapter(leaseList, this); recyclerView.setAdapter(adapter);
Wenn euch das bekannt vorkommt, dann wundert mich das nicht – es ist der gleiche Code wie in onCreate. Für unsere Beispiel-App macht es keinen grossen Unterschied, aber ihr könnt diesen Block aus onCreate entfernen, denn wenn onCreate aufgerufen wird, dann wird in jedem Fall auch onResume aufgerufen (falls ihr nicht so vertraut damit seid, wann welche Methode aufgerufen wird, dann schaut euch die Links am Ende dieses Artikels mal an 😉 ).
Nach diesem kleinen Trick wird unser RecyclerView sowohl einen brandneuen Adapter, als auch eine brandneue Lease-Liste bekommen – jedes Mal wenn es auf den Bildschirm kommt (oder das Telefon z.B. die Ausrichtung ändert) – das ist nicht Effizient, soll für unser Beispiel aber reichen.
Neue Entitäten erzeugen
Wir brauchen immernoch die Möglichkeit, neue Leases in unserer Datenbank zu erzeugen. Lasst uns einfach einen Menüeintrag in MainActivity dafür erzeugen. Öffnet mainMenu.xml im Ordner res/menu, die Datei sollte folgenden Inhalt haben:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context="com.devteam83.tutorials.leasegreendao.MainActivity"> <item android:id="@+id/action_settings" android:title="@string/action_settings" android:orderInCategory="100" android:showAsAction="never" /> </menu>
Wir können das existierende Element wiederverwenden, d.h. wir ersetzen die ID und den Titel. Wenn ihr showAsAction auf „always“ setzt, dann müssen wir nicht extra erst das Menü öffnen – ich finde, dass das nach einer guten Idee klingt.Mein Menü sieht jetzt so aus:
<item android:id="@+id/action_new" android:title="new" android:showAsAction="always" />
Es wäre unheimlich sinnvoll, wenn unser Menüeintrag auch etwas macht (das tut er leider nich nicht). Also öffnen wir MainActivity.java und passen onOptionsItemSelected(MenuItem item) an.
Wir ändern die Zeile „if (id == R.id.action_settings) {“ zu „if (id == R.id.action_new) {„. Der Menüeintrag wird fast das gleiche wie das onClick-Ereignis im ViewHolder machen – es löst einen Intent aus, der LeaseActivity startet, aber mit ID 0:
if (id == R.id.action_new) { Intent intent = new Intent(this, LeaseActivity.class); intent.putExtra("lease_id", 0); this.startActivityForResult(intent, 1); return true; }
Damit wir LeaseActivity nicht unnötig verwirren, müssen wir nocheinmal einen Blick darauf werfen. Wir prüfen bereits, ob leaseId, also die ID aus dem Intent, 0 ist, also fügen wir einfach einen else-Block für unsere Zwecke hinzu. Wenn die ID nicht 0 ist, dann lesen wir den Lease aus der Datenbank, allerdings sind unsere Leases dort ja gar nicht (sie sind eben neu). Lasst uns einfach einen neuen Lease in diesem Fall erzeugen:
if(leaseId != 0 ) { DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); LeaseDao leaseDao = daoSession.getLeaseDao(); lease = leaseDao.load(leaseId); if(lease != null) { editTextItem.setText(lease.getItem()); editTextComment.setText(lease.getComment()); } } else { lease = new Lease(); }
Das wäre schon nicht schlecht, wenn wir denn im Spinner eine Person auswählen könnten, was aber nicht der Fall ist. Als workaround fügen wir etwas Code hinzu, der jedes Mal eine neue Person anlegt, wenn wir einen neuen Lease haben (in LeaseActivity):
buttonSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { lease.setItem(String.valueOf(editTextItem.getText())); lease.setComment(String.valueOf(editTextComment.getText())); DaoSession daoSession = ((LeaseApplication) getApplicationContext()).getDaoSession(); Person person = new Person(); person.setName("John Doe "+ Math.random()); PersonDao personDao = daoSession.getPersonDao(); personDao.insertOrReplace(person); lease.setPerson(person); daoSession.insertOrReplace(lease); finish(); } });
Wir können hier sehr gut sehen, dass ihr mit GreenDAO nicht selbst prüfen müsst, ob eine Entität bereits existiert (und daher geändert werden muss) oder ob sie neu ist (und eingefügt werden muss). Einfach entspannen und GreenDao bei der Arbeit zusehen 😉
WARNUNG! Wenn ihr die App gestartet habt, bevor wir diese letzte Änderung eingefügt haben, dann wird die App in MainActivity abstürzen, weil keine Person in dem Lease ist. Wenn das der Fall ist, dann deinstalliert die App vom Emulator / dem Telefon den/das ihr benutzt und startet einfach nochmal aus Android Studio. Die Datenbank wird neu erstellt und die App funktioniert wieder.
Weitere Schritte
Wir sind am Ende des Themas angelangt, wenn auch in unserer App noch ein paar Dinge zu tun sind. Da wir alle nötigen Fertigkeiten bereits behandelt haben, bin ich zuversichtlich, dass ihr die weiteren Schritte aber allein angehen könnt:
– Activities zum Erstellen, ändern etc. von Person-Entitäten
– den Spinner in LeaseActivity mit Daten füllen
– die in LeaseActivity ausgewählte Person speichern
– die kleinen Abkürzungen, die in der App sind (auch bekannt als schlechter Stil) ersetzen
– Lebenszyklus-Methoden korrekt nutzen
Ich möchte mich noch für die schmutzigen Abkürzungen entschuldigen – ich schätze aber, dass hieraus wohl 14 Teile geworden währen, wenn ich alles ordentlich gemacht hätte.
Themen zum Weiterlesen
Wenn das hier euer erster Kontakt mit GreenDAO oder vielleicht sogar Android-Programmierung war:
Herzlichen Glückwunsch!
Vielleicht solltet ihr einen Blick auf die folgenden Resourcen riskieren:
– greenrobots Webseite (von den Erstellern von greenDAO)
– Android Lebenszyklus auf Android Developers
– wenn Android-Entwicklung komplett neu für euch ist, dann könnt ihr euch ja mal „Android Programming: The Big Nerd Ranch Guide“ ansehen (nein, wir kennen die Autoren nicht) – leicht zu lesen, viele Themen abgedeckt (aber keine OR-Mapper 😉 )
Ich hoffe ihr hattet beim Lesen dieser Serie so viel Freude wie ich beim Schreiben, danke, dass ihr durch alle 4 Teile gegangen seid.
Wenn ihr Fragen oder Kommentare zu den 4 Teilen habt, oder Hilfe bei den „Nächsten Schritten braucht – lasst einen Kommentar da!