ListView - Aktualisierung durch Button

  • Antworten:7
Frank Rudolf
  • Forum-Beiträge: 215

09.12.2015, 11:22:11 via Website

Hinweis: weiter unten habe ich das Problem noch mal in geraffter Form dargestellt.

strong text**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;

ArrayListtreffer = new ArrayList(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(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.

— geändert am 09.12.2015, 17:48:06

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

09.12.2015, 13:47:36 via Website

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

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

Nachdem du "VaterSuchen" benutzt hast musst du die ListView natürlich wieder aktualisierren.
Oder du schiebt das einfach hoch und dann so:

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

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

LG Pascal //It's not a bug, it's a feature. :) ;)

Frank Rudolf

Antworten
Frank Rudolf
  • Forum-Beiträge: 215

09.12.2015, 14:14:28 via Website

Pascal,

hat leider nicht funktioniert.

Bei der ListView ist es auch so, dass ich zuerst clear und notify sage und dann erst werden die neuen Daten für den Adapter generiert. Diese Reihenfolge müßte ja eigentlich dann auch für den Button gelten.

Komisch finde ich allerdings auch, dass nach dem Generieren der neuen Daten scheinbar (?) kein weiterer Bezug zur ListView aufgebaut wird. Das Erzeugen der neuen Daten reicht zur Neudarstellung der ListView.

Vielleicht fehlt bei Benutzung per Button etwas, dass hier bei der ListView berücksichtigt wird:
public void onItemClick(AdapterView adapterView, View view, int position, long id)

— geändert am 09.12.2015, 14:16:43

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

09.12.2015, 14:25:03 via Website

Ich weiss was du vergessen hast ;9

ListView#setAdapter() musst du wieder machen, da du eine neue Adapterinstanz machst.
Warum eigentlich?
Hast du ein Anderes Layout oder bleibt das glecih?
Wenn es gleich bleibt kannst du dir das auch sparen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Frank Rudolf

Antworten
Frank Rudolf
  • Forum-Beiträge: 215

09.12.2015, 17:24:40 via Website

Habs mit setAdapter versucht. Dabei ist es wenigstens zum Clearen des ListViews gekommen. Eine Aktualisierung gelang aber nicht.

Ich stelle das Problem noch mal deutlicher dar.

Antworten
Frank Rudolf
  • Forum-Beiträge: 215

09.12.2015, 17:45:57 via Website

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

final ArrayAdapter adapter = new ArrayAdapter(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:

b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ArrayAdapter adapter = new ArrayAdapter(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;

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

09.12.2015, 18:08:41 via Website

Lass das adaper.clear() weg und mach lieber treffer.clear();

LG Pascal //It's not a bug, it's a feature. :) ;)

Frank Rudolf

Antworten
Frank Rudolf
  • Forum-Beiträge: 215

10.12.2015, 16:28:32 via Website

Das mit dem Treffer.clear() muss ich noch mal durchdenken.

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.

Antworten