ListView - Aktualisierung durch Button

J

Jusehr

Neues Mitglied
0
Eine vereinfachte Fassung des Problems siehe unten unter Beitrag #3!

Das Projekt besteht bisher aus einer ListView und einem Button.

Die Daten, die im ListView angezeigt werden sollen, befinden sich in der strings.xml. Die Daten sind durch ihre ID hierarchisch organisiert (spielt für mein Problem aber keine Rolle). Zu Programmbeginn zeige ich die oberste Ebene (zB Erdteile) an. Per Klick auf einen ListView-Item (zB Europa) werden die Länder Europas im ListView angezeigt. Per Klick auf Deutschland zB werden die Bundesländer Deutschlands angezeigt etc.

Der Button dient dazu, in der Hierarchie der Daten eine Ebene noch oben zu gehen. Von der Bundesländerebene Deutschlands zB eine Ebene nach oben zu den Ländern Europas.

Die meines Erachtens relevanten Codeteile:


import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu; import android.view.MenuItem;

import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;

import android.util.Log;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
String msg = "Meldung:";
Button b1, b2;
String vater;

ArrayList<String>treffer = new ArrayList<String>(250);

@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = (Button)findViewById(R.id.button);
b1.setOnClickListener(new View.OnClickListener() {
@override
public void onClick(View v) {//############################################################
final ArrayAdapter adapter = new ArrayAdapter<String>(getApplication(), R.layout.activity_listview, treffer);
adapter.clear();
adapter.notifyDataSetChanged();
VaterSuchen(vater);

}//-------------------------------------------------------------------------------------
});//-----------------------------------------------------------------------------------

final ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.activity_listview, treffer);
DatensatzHolen3("v0id0");
ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);
//Code für Klick auf Listenelement##########################################################
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
String information = (String) adapterView.getItemAtPosition(position);
vater = information;

int iPosition = information.indexOf(' ');
String id2 = information.substring(0,iPosition);
adapter.clear();
adapter.notifyDataSetChanged();
DatensatzHolen3(id2);

}
});//---------------------------------------------------------------------------------------

...

public String VaterSuchen(String kennung){
Log.d("auf Vater suchen gekli",kennung);
int iPosition;
String neueKennung;
iPosition = kennung.indexOf(' ');
neueKennung = kennung.substring(0, iPosition);//zB v123id33

iPosition = neueKennung.indexOf('i');
neueKennung = neueKennung.substring(0, iPosition);//zB v123

DatensatzHolen3(neueKennung);
return "d";
}
public String DatensatzHolen3(String kennung) {
int iPosition;
int i = 0;
iPosition = kennung.indexOf('i');
String id2 = kennung.substring(iPosition + 2);// zB 26
String suchmuster = "v" + id2 + "id";

for (Field field : R.string.class.getDeclaredFields()) {
String vid = field.getName();

if (vid.startsWith(suchmuster)) {
int id = getResources().getIdentifier(field.getName(), "string", getPackageName());
String value = (String) getResources().getText(id);

treffer.add(field.getName()+ " " + value);
i++;
}


}

return "d";
}

Der Code läuft fehlerfrei. Jedoch passiert nichts, wenn ich mich auf einer unteren Ebene der Daten befinde und auf den Button klicke. Das Problem dürfte also im ClickListener des Buttons zu finden sein:

final ArrayAdapter adapter = new
ArrayAdapter<String>(getApplication(), R.layout.activity_listview,

treffer); adapter.clear(); adapter.notifyDataSetChanged();
VaterSuchen(vater);


getApplication habe ich bereits ersetzt. Vorher stand da this, was sofort beanstandet wurde. Die Frage scheint zu sein, wie ich im ClickListner des Buttons einen Bezug zum Adapter und der Listview hinkriege.

Ich weiß, dass der Code noch nicht der objektorientierten Programmierung entspricht und noch recht prozedural aufgebaut ist. Man müßte zB sinnvollerweise noch eine Klasse Datensatz etc. einführen. Auch die Returns müßte ich wohl um entsprechende Voids ersetzen. Aber darum geht es hier nicht primär.
 
Zuletzt bearbeitet:
Sorry aber den Code kann man kaum lesen auf die schnelle. Könntest du den formatieren vllt?

mit

[//CODE=Java]

Hier Code rein und die "//" im ersten Tag entfernen;

[/Code]

Also ungefähr so:

Java:
    Genauso;
        Bitte mit Einrückungen;

Ansonsten verstehe ich den Sinn davon hier nicht:
Java:
adapter.clear();
adapter.notifyDataSetChanged();

Also die Reihenfolge jedenfalls...
 
  • Danke
Reaktionen: Jusehr
Ich versuche mal eine kürzere und leserlichere Fassung. Dauert noch ein Weilchen.
[doublepost=1449662590,1449662041][/doublepost]Dieser Code in der ActivityMain läuft:

Java:
final ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.activity_listview, treffer);
DatensatzHolen3("v0id0");

ListView listView = (ListView) findViewById(R.id.mobile_list);
listView.setAdapter(adapter);

//Code für Klick auf Listenelement
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    [USER=3517]@override[/USER]
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        String information = (String) adapterView.getItemAtPosition(position);
        vater = information;
   
        int iPosition = information.indexOf(' ');
        String id2 = information.substring(0,iPosition);

        adapter.clear();
        adapter.notifyDataSetChanged();
        DatensatzHolen3(id2);
  
    }
});//---------------------------------------------------------------------------------------

Der ähnlich aufgebaute Code im Button läuft nicht (keine Reaktion, aber auch keine Fehlermeldung).

Java:
b1.setOnClickListener(new View.OnClickListener() {
    [USER=3517]@override[/USER]
    public void onClick(View v) {//############################################################
        final ArrayAdapter adapter = new ArrayAdapter<String>(getApplication(), R.layout.activity_listview, treffer);
        adapter.clear();
        adapter.notifyDataSetChanged();
        VaterSuchen(vater);
    }
});

Meines Erachtens steckt das Problem in der noch nicht funktionierenden Zeile
Java:
final ArrayAdapter adapter = new ArrayAdapter<String>(getApplication(), R.layout.activity_listview, treffer);
Hier hatte ich auch schon this durch getApplication getauscht. Geht dennoch nicht.
 
Zuletzt bearbeitet:
Ich sehe keinen grund für Java Reflections aber du hast da wohl deine Gründe dafür :)

Hilft es wenn du adapter.notifyDataSetChanged(); ganz ans Ende der onClick() Methoden stellst?

Deswegen meine Anmerkung dass die Reihenfolge komisch ist.
Erst Clearst du, dann sagst du dass sich was geändert hat und es soll aktualisiert werden. Dann änderst du die Quelle Arraylist<String> vom Adapter ohne ihm Bescheid zu geben dass sich was verändert hat. Also hängt der immer noch im Clear Status rum obwohl du deine View gerne nneu populieren möchtest :(
 
  • Danke
Reaktionen: Jusehr
Nochmal vereinfacht:

In **onCreate** werden ein ListView und der dazugehörige Adapter produziert:

Java:
final ArrayAdapter adapter = new ArrayAdapter<String>(this,
R.layout.activity_listview, treffer);
  ...
ListView listView = (ListView) findViewById(R.id.mobile_list); listView.setAdapter(adapter);
  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
  String information = (String) adapterView.getItemAtPosition(position);
  ...
  adapter.clear();
  adapter.notifyDataSetChanged();
  ...
  }
  });
Das Projekt beinhaltet auch noch einen Button, der ebenfalls den Inhalt des ListViews aktualisieren soll:

Java:
 b1.setOnClickListener(new View.OnClickListener() {
  [USER=3517]@override[/USER]
  public void onClick(View v) {
  ArrayAdapter adapter = new ArrayAdapter<String>(getApplication(), R.layout.activity_listview,
 treffer);
  ListView listView = (ListView) findViewById(R.id.mobile_list);
  listView.setAdapter(adapter);
  adapter.clear();
  //Hier steht Code, der die DatenGrundlage für die Aktualisierung der ListView liefert
  adapter.notifyDataSetChanged();
  }
  });

Der Code für das ListView funktioniert wie gewünscht. Der Code für den Button löst keinen Fehler aus, cleart aber nur das ListView.

Den Code im ClickListener des Buttons habe ich in Anlehnung an den Code des ClickListeners der ListView gefertigt. Das doppelte Anlegen des Adapters erschien mir notwendig, da er sonst nicht im ClickListener des Buttons erkannt wurde. Das Anlegen des Adapters als "globale Variable" in der MainActivity (also eine Ebene höher) brachte nichts: ArrayAdapter adapter;
 
Ich bin mir bei dem einen Konstrukt nciht sicher ob das gewollt ist was da heraus kommt:

Vielleicht
mal das versuchen
Code:
ArrayAdapter<String> adapter ...
statt
Code:
ArrayAdapter adapter = ...

Oder statt getApplication() mal getBaseContext() versuchen???

Ich weiß nciht ob es Vorteile bringt den Adapter zu clearen aber reicht es nciht aus einfach nur das Array dahinter zu verändern und den bestehenden Adapter davon zu informieren?
 
  • Danke
Reaktionen: Jusehr
Wollte erst mal schildern, welche Beobachtung ich gestern noch gemacht habe.

Scheinbar funktioniert der Code. Allerdings erhalte ich eine ganz schwache (kontrastschwache) Anzeige im ListView. So schwach, dass ich sie vielleicht verfrüht als Clearergebnis interpretiert habe. **Vielleicht funktioniert irgendetwas mit dem Rendern nicht?**

Werde mir mal überlegen, ob ich den Weg mit dem Button (erst mal) weitergehe oder ob ich vielleicht beim ListView bleibe und stattdessen zB eine Checkbox anbringe, mit der ich sage, dass ich eine Ebene höher gehen möchte. Die dazugehörigen Befehle würden also ebenfalls über den ClickListener der ListView ausgelöst. Der funktioniert ja im Augenblick fehlerlos.
 
Hast du den Rat von Jaiel befolgt, und die Methode adapter.clear() auskommentiert?
 
  • Danke
Reaktionen: Jusehr
markus.tullius schrieb:
Hast du den Rat von Jaiel befolgt, und die Methode adapter.clear() auskommentiert?

Ich hab's gerade gemacht. Ergebnis dasselbe. Wie gesagt: ich nehme nun - mit oder ohne Clearen des Adapters - korrekte Daten allerdings in weißer Schrift auf sehr hellem Grau wahr. Da es noch einen Fehler im Algorithmus gibt, bin ich noch nicht zum weiteren Testen gekommen.

Vermutlich gehe ich weiter über den Weg integrierter Buttons auf jedem ListViewItem. Oder ich nehme erst mal den uneleganteren Weg über eine Checkbox außerhalb der ListView, mit der ich anzeigen kann, ob ich in der Hierarchie der Daten ab- oder aufwärts steigen will. Aber der Hintergrund der blassen Darstellung würde mich schon auch noch interessieren.
 
Also. Ich habe jetzt alles in den Listener der ListView gepackt. Und es lief auch in der korrekten optischen Darstellung, was ich wohl durch das Weglassen der Neuinitialisierung des Adapters erreicht habe.

Allerdings habe ich ein neues Problem. Aber erst mal der wenigstens übersichtlicherere Code:
Java:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        //String information = (String) adapterView.getItemAtPosition(position);

        if (cb.isChecked()){
            ListView listView = (ListView) findViewById(R.id.mobile_list);
            listView.setAdapter(adapter);
            adapter.clear();
            adapter.notifyDataSetInvalidated();
            String information = (String) adapterView.getItemAtPosition(position);
            ...
        }else {
            String information = (String) adapterView.getItemAtPosition(position);
            vater = information;
            int iPosition = information.indexOf(' ');
            String id2 = information.substring(0, iPosition);

            adapter.clear();
            adapter.notifyDataSetChanged();
            DatensatzHolen3(id2);
        }
    }
});

Eine Checkbox bewirkt nun die Unterscheidung, ob ich im Informationsbaum runter oder rauf gehen will. Also Vater (mit eventuellen Geschwistern) oder Kinder suchen.

Das Problem erfolgt in der Zeile:
Java:
String information = (String) adapterView.getItemAtPosition(position);
, die im oberen und unteren Zweig auftaucht und noch mal ganz oben (als Überbleibsel eines "globalen" Versuchs) auskommentiert. Innerhalb des CodeBlocks scheint das Fetten nicht zu funktionieren.
Der unten stehende Teil (Checkbox nicht geckeckt) funktioniert. Der oben stehende Teil (Checkbox aktiviert) funktioniert nicht. Die Zeile bewirkt, dass ich den Inhalt des angeklickten Items bekomme, den ich dann weiter verarbeite.

Der Debugger scheint zu bemängeln, dass er im ersten oberen Teil "die lokale Variable information nicht finden kann". Habe schon einiges versucht: Deklaration ganz oben im Listener (wie man oben sieht auskommentiert), Verwendung zwei unterschiedlicher Variablennamen etc. Warum geht das nicht? Ist das ein Sichtbarkeitsproblem oder doch was anderes? Mir ist wohl bekannt, dass Variablen bei Java innerhalb einer tieferen {-Ebene quasi lokal sind etc.
 
Zuletzt bearbeitet:
Es scheint jetzt zu gehen. Es würde mich aber nicht wundern, wenn ich mich Anfang nächster Woche wieder bei Euch melde :smile:. Das Projekt ist ja noch längst nicht fertig.

Gutes Wochenende für Euch!

Der code sieht jetzt übrigens so aus:
Java:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
       
        if (cb.isChecked()){
            adapter.clear();
            adapter.notifyDataSetChanged();
            String ergebnis = VaterSuchen("v1811id1844");//das wird noch dynamisiert
            ergebnis = VaterSuchen(ergebnis);
            DatensatzHolen3(ergebnis);
        }else {
            String information = (String) adapterView.getItemAtPosition(position);
            vater = information;
            int iPosition = information.indexOf(' ');
            String id2 = information.substring(0, iPosition);

            adapter.clear();
            adapter.notifyDataSetChanged();
            DatensatzHolen3(id2);
       
        }
    }
});
 

Ähnliche Themen

A
  • AnimaAngelo85
Antworten
1
Aufrufe
341
swa00
swa00
MES
Antworten
10
Aufrufe
827
MES
MES
A
Antworten
10
Aufrufe
1.025
swa00
swa00
Zurück
Oben Unten