Wie aktualisiere ich die Android-Listenansicht?

Antworten:

530

Rufen Sie notifyDataSetChanged()Ihr AdapterObjekt auf, sobald Sie die Daten in diesem Adapter geändert haben.

notifyDataSetChanged()In diesem Google I / O-Video finden Sie einige zusätzliche Informationen dazu, wie / wann Sie anrufen müssen .

Christopher Orr
quelle
24
Sie sollten es auf dem UI-Thread ausführen. Erstellen Sie einen Handler innerhalb des UI-Threads und posten Sie dann Runable darauf
Kirill Kulakov
11
Noch einmal: notifyDataSetChanged () funktioniert zumindest nicht für empfohlene Verwendungspraktiken (lesen Sie nicht veraltet). Wenn Sie Listenansicht, Cursoradapter und Inhaltsanbieter verwenden, versuchen Sie möglicherweise Folgendes: gettLoaderManager (). RestartLoader (). Siehe: stackoverflow.com/a/19657500/1087411 Ich möchte zumindest einige Dokumentationen zu notifyDataSetChanged () sehen. Zu viel in Android bleibt dem Black-Box-Testen überlassen.
Anderson
Wenn notifyDataSetChanged nicht funktioniert, sind Sie derjenige, der es falsch macht
zdarsky.peter
4
notifyDataSetChanged funktioniert nicht immer. Ich bin mir nicht sicher, warum dies umstritten ist. Manchmal müssen Sie listView.setAdapter (Adapter) aufrufen, um die alten Ansichten zu löschen. Siehe auch: stackoverflow.com/a/16261588/153275
1
Ich konnte notifyDataSetChanged nie zum Laufen bringen. Ich konnte deutlich sehen, dass sich die Sammlung, die ich dem Adapter zuführe, geändert hat (Elemente wurden entfernt), aber notifyDataSetChanged hat nie etwas getan. Nicht sicher, ob diese Methode nur kaputt ist?
bis zum
204

Sie können auch Folgendes verwenden:

myListView.invalidateViews();
Bobs
quelle
22
Dies ist die richtige Antwort, wenn Sie nur die Ansicht neu zeichnen müssen. Zum Beispiel, nachdem eine Benutzeranmeldung erfolgt ist, die weitere Informationen oder Optionen in jeder Ansicht der listView verfügbar machen muss. Das war es, was ich tun musste, also gab ich eine Gegenstimme. Wenn sich die zugrunde liegenden Daten ändern, ist es wahrscheinlich besser, notifyDataSetChanged () zu verwenden.
SBerg413
Eigentlich invalidateViews()in den Quellcodesätzen, mDataChanged = true;also bin ich mir nicht sicher, ob dies zu einer besseren Leistung führt alsnotifyDataSetChanged()
vovahost
Du hast meinen Tag gerettet, Alter!
oskarko
Sie können eine Art von Liste nehmen, die "beobachtbare Liste" ist, ohne dass eine Änderung des Datasets erforderlich ist
Priya
153

Bitte ignorieren Sie alle die invalidate(), invalidateViews(), requestLayout(), ... Antworten auf diese Frage.

Das Richtige (und glücklicherweise auch als richtige Antwort markiert) ist , notifyDataSetChanged()Ihren Adapter anzurufen .

Fehlerbehebung

Wenn der Aufruf notifyDataSetChanged()nicht funktioniert, helfen auch nicht alle Layoutmethoden. Glauben Sie mir, das ListViewwurde richtig aktualisiert. Wenn Sie den Unterschied nicht finden, müssen Sie überprüfen, woher die Daten in Ihrem Adapter stammen.

Wenn dies nur eine Sammlung ist, die Sie im Speicher behalten, überprüfen Sie, ob Sie die Elemente tatsächlich aus der Sammlung gelöscht oder hinzugefügt haben, bevor Sie die aufrufen notifyDataSetChanged().

Wenn Sie mit einem Datenbank- oder Service-Backend arbeiten, müssen Sie die Methode aufrufen, um die Informationen erneut abzurufen (oder die In-Memory-Daten zu bearbeiten), bevor Sie das aufrufen notifyDataSetChanged().

Die Sache ist, dass dies notifyDataSetChangednur funktioniert, wenn sich der Datensatz geändert hat. Das ist also der richtige Ort, wenn Sie keine Änderungen feststellen. Debuggen Sie bei Bedarf.

ArrayAdapter vs BaseAdapter

Ich habe festgestellt, dass die Arbeit mit einem Adapter, mit dem Sie die Sammlung verwalten können, wie ein BaseAdapter, besser funktioniert. Einige Adapter wie der ArrayAdapter verwalten bereits ihre eigene Sammlung, was es schwieriger macht, zur richtigen Sammlung für Updates zu gelangen. In den meisten Fällen ist es wirklich nur eine unnötige zusätzliche Schwierigkeitsstufe.

UI-Thread

Es ist wahr, dass dies vom UI-Thread aufgerufen werden muss. Andere Antworten enthalten Beispiele, wie dies erreicht werden kann. Dies ist jedoch nur erforderlich, wenn Sie diese Informationen von außerhalb des UI-Threads bearbeiten. Das ist von einem Dienst oder einem Nicht-UI-Thread. In einfachen Fällen aktualisieren Sie Ihre Daten durch einen Klick auf eine Schaltfläche oder eine andere Aktivität / ein anderes Fragment. Also immer noch im UI-Thread. Sie müssen diesen runOnUiTrhead nicht immer einfügen.

Schnelles Beispielprojekt

Kann unter https://github.com/hanscappelle/so-2250770.git gefunden werden . Klonen und öffnen Sie das Projekt einfach in Android Studio (gradle). Dieses Projekt verfügt über ein MainAcitivity-Gebäude ListViewmit allen zufälligen Daten. Diese Liste kann über das Aktionsmenü aktualisiert werden.

Die Adapterimplementierung, die ich für dieses Beispiel ModelObject erstellt habe, macht die Datenerfassung verfügbar

public class MyListAdapter extends BaseAdapter {

    /**
     * this is our own collection of data, can be anything we 
     * want it to be as long as we get the abstract methods 
     * implemented using this data and work on this data 
     * (see getter) you should be fine
     */
    private List<ModelObject> mData;

    /**
     * our ctor for this adapter, we'll accept all the things 
     * we need here
     *
     * @param mData
     */
    public MyListAdapter(final Context context, final List<ModelObject> mData) {
        this.mData = mData;
        this.mContext = context;
    }

    public List<ModelObject> getData() {
        return mData;
    }

    // implement all abstract methods here
}

Code aus der Hauptaktivität

public class MainActivity extends Activity {

    private MyListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list = (ListView) findViewById(R.id.list);

        // create some dummy data here
        List<ModelObject> objects = getRandomData();
        // and put it into an adapter for the list
        mAdapter = new MyListAdapter(this, objects);
        list.setAdapter(mAdapter);

        // mAdapter is available in the helper methods below and the 
        // data will be updated based on action menu interactions

        // you could also keep the reference to the android ListView 
        // object instead and use the {@link ListView#getAdapter()} 
        // method instead. However you would have to cast that adapter 
        // to your own instance every time
    }

    /**
     * helper to show what happens when all data is new
     */
    private void reloadAllData(){
        // get new modified random data
        List<ModelObject> objects = getRandomData();
        // update data in our adapter
        mAdapter.getData().clear();
        mAdapter.getData().addAll(objects);
        // fire the event
        mAdapter.notifyDataSetChanged();
    }

    /**
     * helper to show how only changing properties of data 
     * elements also works
     */
    private void scrambleChecked(){
        Random random = new Random();
        // update data in our adapter, iterate all objects and 
        // resetting the checked option
        for( ModelObject mo : mAdapter.getData()) {
            mo.setChecked(random.nextBoolean());
        }
        // fire the event
        mAdapter.notifyDataSetChanged();
    }
}

Mehr Informationen

Ein weiterer netter Beitrag über die Leistungsfähigkeit von listViews finden Sie hier: http://www.vogella.com/articles/AndroidListView/article.html

hcpl
quelle
16
du liegst falsch. notifyDataSetChanged () hat bei mir nicht funktioniert, aber invalidateViews () hat es richtig gemacht.
Babay
6
Ich habe das Problem, dass sich die tatsächlichen Elemente in der Liste nicht ändern, z. B. die gleiche Anzahl von Elementen. Das Problem ist jedoch, dass sich die Art und Weise, wie sie präsentiert werden, ändern muss. Das bedeutet, dass der Code meines Adapters zum Erstellen der Benutzeroberfläche erneut ausgeführt werden muss und dann ein Element in den Listenzeilen korrekt ausgeblendet werden muss. notifyDataSetChanged () funktioniert nicht ...
Sven Haiges
9
Diese Antwort hat mir wirklich geholfen. Ich habe das Array aus bestimmten Gründen im Speicher behalten. Um das adapter.clear()adapter.addAll(Array<T>)notifyDataSetChanged()
Problem
2
@hcpl, wie soll ich notifyDataSetChanged aufrufen, wenn ich mich im OnClickListener des Adapters für eine CheckBox befinde? invalidateViews erledigt den Job gerade. Warum ist invalidateViews die falsche Methode zum Aufrufen?
Craned
1
Ich konnte notifyDataSetChanged nie zum Laufen bringen. Ich konnte deutlich sehen, dass sich die Sammlung, die ich dem Adapter zuführe, geändert hat (Elemente wurden entfernt), aber notifyDataSetChanged hat nie etwas getan. Nicht sicher, ob diese Methode nur kaputt ist?
bis zum
42

Rufen Sie runnable an, wann immer Sie möchten:

runOnUiThread(run);

OnCreate(), setzen Sie Ihren ausführbaren Thread:

run = new Runnable() {
    public void run() {
        //reload content
        arraylist.clear();
        arraylist.addAll(db.readAll());
        adapter.notifyDataSetChanged();
        listview.invalidateViews();
        listview.refreshDrawableState();
    }
};
Marckaraujo
quelle
1
Funktioniert auch in meinem Fall, in dem ich eine Listenansicht basierend auf Daten aktualisieren muss, die von einer TCP-Verbindung stammen (von einem "nonUI" -Thread). Die einzige Möglichkeit, die Liste neu zu zeichnen, bestand darin, alle Elemente der ArrayList zu löschen und erneut hinzuzufügen. Wenn Sie sich bereits im UI-Thread befinden, müssen Sie den Code nicht über die runOnUiThread()Funktion aufrufen .
Andre
Vielen Dank! Für mich geht das. Für alle Personen, die dies von einem Fragment aus ausführen möchten, sollten Sie getActivity (). RunOnUiThread (new Runnable ...) verwenden, um sicherzustellen, dass der Code auf dem UI-Thread ausgeführt wird
Codierungspuss
Ich sehe den Zweck nicht run = new Runnable()und habe meiner Funktion nur eine public void refreshUIThread()Methode gegeben, die Ihre run()Methode modelliert (was auch funktioniert).
T. Woody
11

Ich habe einige Probleme mit der dynamischen Aktualisierung meiner Listenansicht.

Rufen Sie notifyDataSetChanged () auf Ihrem Adapter auf.

In diesem Google I / O-Video können einige zusätzliche Details zum Aufrufen von notifyDataSetChanged () angezeigt werden.

notifyDataSetChanged () funktionierte in meinem Fall nicht richtig [Ich habe notifyDataSetChanged von einer anderen Klasse aufgerufen]. Nur für den Fall, dass ich die ListView in der laufenden Aktivität (Thread) bearbeitet habe. Das Video dank Christopher gab den letzten Hinweis.

In meiner zweiten Klasse habe ich verwendet

Runnable run = new Runnable(){
     public void run(){
         contactsActivity.update();
     }
};
contactsActivity.runOnUiThread(run);

um auf das update () aus meiner Aktivität zuzugreifen. Dieses Update enthält

myAdapter.notifyDataSetChanged();

um den Adapter anzuweisen, die Ansicht zu aktualisieren. Hat gut funktioniert, soweit ich sagen kann.

Wille
quelle
5

Wenn Sie mit der ListView-Aktualisierung immer noch nicht zufrieden sind, können Sie sich dieses Snippet ansehen. Dies dient zum Laden der listView aus der Datenbank. Sie müssen die ListView lediglich neu laden, nachdem Sie eine CRUD-Operation ausgeführt haben. Dies ist kein bester Weg Code, aber es wird die ListView nach Ihren Wünschen aktualisieren.

Es funktioniert für mich .... wenn Sie eine bessere Lösung finden, teilen Sie bitte ...

....... .......
......
Führen Sie Ihre CRUD-Operationen durch.
......
..... .....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Bringe diese DB_Ergebnisse und füge sie als Inhalt zur Liste hinzu ....
                                            ls2.setAdapter (neuer ArrayAdapter (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
                                            DBAdapter.close ();
Nandagopal T.
quelle
2

Die von den Personen in diesem Beitrag vorgeschlagenen Lösungen funktionieren oder hängen nicht hauptsächlich von der Android-Version Ihres Geräts ab. Um beispielsweise die AddAll-Methode zu verwenden, müssen Sie android: minSdkVersion = "10" in Ihr Android-Gerät einfügen.

Um diese Fragen für alle Geräte zu lösen, habe ich meine eigene Methode in meinem Adapter erstellt und innerhalb der von ArrayAdapter geerbten Methode zum Hinzufügen und Entfernen verwendet, mit der Sie Ihre Daten problemlos aktualisieren können.

Mein Code: Mit meiner eigenen Datenklasse RaceResult verwenden Sie Ihr eigenes Datenmodell.

ResultGpRowAdapter.java

public class ResultGpRowAdapter extends ArrayAdapter<RaceResult> {

    Context context;
    int resource;
    List<RaceResult> data=null;

        public ResultGpRowAdapter(Context context, int resource, List<RaceResult> objects)           {
        super(context, resource, objects);

        this.context = context;
        this.resource = resource;
        this.data = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ........
        }

        //my own method to populate data           
        public void myAddAll(List<RaceResult> items) {

        for (RaceResult item:items){
            super.add(item);
        }
    }

ResultsGp.java

public class ResultsGp extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {

    ...........
    ...........
    ListView list = (ListView)findViewById(R.id.resultsGpList); 

    ResultGpRowAdapter adapter = new ResultGpRowAdapter(this,  R.layout.activity_result_gp_row, new ArrayList<RaceResult>()); //Empty data

   list.setAdapter(adapter);

   .... 
   ....
   ....
   //LOAD a ArrayList<RaceResult> with data

   ArrayList<RaceResult> data = new ArrayList<RaceResult>();
   data.add(new RaceResult(....));
   data.add(new RaceResult(....));
   .......

   adapter.myAddAll(data); //Your list will be udpdated!!!
AntuanSoft
quelle
1

Wenn Sie Ihre Bildlaufposition beim Aktualisieren beibehalten möchten, können Sie dies tun:

if (mEventListView.getAdapter() == null) {
    EventLogAdapter eventLogAdapter = new EventLogAdapter(mContext, events);
    mEventListView.setAdapter(eventLogAdapter);
} else {
    ((EventLogAdapter)mEventListView.getAdapter()).refill(events);
}

public void refill(List<EventLog> events) {
    mEvents.clear();
    mEvents.addAll(events);
    notifyDataSetChanged();
}

Ausführliche Informationen finden Sie unter Android ListView: Behalten Sie Ihre Bildlaufposition bei, wenn Sie aktualisieren .

Brandon Yang
quelle
1

Verwenden Sie einfach myArrayList.remove(position);in einem Hörer:

  myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
           myArrayList.remove(position);
           myArrayAdapter.notifyDataSetChanged();
        }
    });
Steffo Dimfelt
quelle
1

Sie müssen ein einzelnes Objekt dieser Liste verwenden, dessen Daten Sie aufblasen ListView. Wenn die Referenz notifyDataSetChanged()geändert wird, funktioniert dies nicht. Wenn Sie Elemente aus der Listenansicht löschen, löschen Sie sie auch aus der Liste, die Sie verwenden, unabhängig davon, ob es sich um eine ArrayList <> oder etwas anderes handelt. Rufen Sie dann das notifyDataSetChanged()Objekt Ihrer Adapterklasse auf.

Also hier sehen Sie, wie ich es in meinem Adapter geschafft habe, siehe unten

public class CountryCodeListAdapter extends BaseAdapter implements OnItemClickListener{

private Context context;
private ArrayList<CountryDataObject> dObj;
private ViewHolder holder;
private Typeface itemFont;
private int selectedPosition=-1;
private ArrayList<CountryDataObject> completeList;

public CountryCodeListAdapter(Context context, ArrayList<CountryDataObject> dObj) {
    this.context = context;
    this.dObj=dObj;
    completeList=new  ArrayList<CountryDataObject>();
    completeList.addAll(dObj);
    itemFont=Typeface.createFromAsset(context.getAssets(), "CaviarDreams.ttf");
}

@Override
public int getCount() {
    return dObj.size();
}

@Override
public Object getItem(int position) {
    return dObj.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
    if(view==null){
        holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.states_inflator_layout, null);
        holder.textView = ((TextView)view.findViewById(R.id.stateNameInflator));
        holder.checkImg=(ImageView)view.findViewById(R.id.checkBoxState);
        view.setTag(holder);
    }else{
        holder = (ViewHolder) view.getTag();
    }
    holder.textView.setText(dObj.get(position).getCountryName());
    holder.textView.setTypeface(itemFont);

    if(position==selectedPosition)
     {
         holder.checkImg.setImageResource(R.drawable.check);
     }
     else
     {
         holder.checkImg.setImageResource(R.drawable.uncheck);
     }
    return view;
}
private class ViewHolder{
    private TextView textView;
    private ImageView checkImg;
}

public void getFilter(String name) {
    dObj.clear();
    if(!name.equals("")){
    for (CountryDataObject item : completeList) {
        if(item.getCountryName().toLowerCase().startsWith(name.toLowerCase(),0)){
            dObj.add(item);
        }
    }
    }
    else {
        dObj.addAll(completeList);
    }
    selectedPosition=-1;
    notifyDataSetChanged();
    notifyDataSetInvalidated(); 
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    Registration reg=(Registration)context;
    selectedPosition=position;
    reg.setSelectedCountryCode("+"+dObj.get(position).getCountryCode());
    notifyDataSetChanged();
}
}
ADM
quelle
1
Ihre Erklärung wird unterschätzt, aber es gibt mir wirklich Verständnis für die Referenz der Arraylisten. Vielen Dank
Abraham Putra Prakasa
0

Nach dem Löschen von Daten aus der Listenansicht müssen Sie anrufen refreshDrawableState(). Hier ist das Beispiel:

final DatabaseHelper db = new DatabaseHelper (ActivityName.this);

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

und deleteContactMethode in der DatabaseHelperKlasse wird etwas aussehen

public boolean deleteContact(long rowId) {

   return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0;

}
user1031852
quelle
0

Ich konnte notifyDataSetChanged () nicht dazu bringen, an der Aktualisierung meines SimpleAdapter zu arbeiten. Stattdessen habe ich versucht, zuerst alle Ansichten zu entfernen, die mit removeAllViews () an das übergeordnete Layout angehängt wurden, dann die ListView hinzuzufügen, und das hat funktioniert, sodass ich die aktualisieren konnte Benutzeroberfläche:

LinearLayout results = (LinearLayout)findViewById(R.id.results);
ListView lv = new ListView(this);
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row, 
                new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } );

for (...) { 
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", name);
    map.put("dept", dept);
    list.add(map);
}

lv.setAdapter(adapter);
results.removeAllViews();     
results.addView(lv);
Chasden
quelle
0

Für mich konnte nach dem Ändern der Informationen in der SQL-Datenbank nichts die Listenansicht aktualisieren (um eine bestimmte erweiterbare Listenansicht zu sein). Wenn notifyDataSetChanged () nicht hilft, können Sie versuchen, Ihre Liste zuerst zu löschen und sie nach diesem Aufruf notifyDataSetChanged () erneut hinzuzufügen. Zum Beispiel

private List<List<SomeNewArray>> arrayList;
List<SomeNewArray> array1= getArrayList(...);
List<SomeNewArray> array2= getArrayList(...);
arrayList.clear();
arrayList.add(array1);
arrayList.add(array2);
notifyDataSetChanged();

Hoffe es macht Sinn für dich.

Aivus
quelle
0

Bei Verwendung von SimpleCursorAdapter kann changeCursor (newCursor) auf dem Adapter aufgerufen werden.

Vihaan Verma
quelle
0

Ich war das gleiche, als ich in einem Fragment eine ListView (in einer einzelnen TextView) mit der Mac-Adresse von BLE-Geräten füllen wollte, die über einen längeren Zeitraum gescannt wurden.

Was ich getan habe war folgendes:

public class Fragment01 extends android.support.v4.app.Fragment implements ...
{
    private ListView                listView;
    private ArrayAdapter<String>    arrayAdapter_string;

...

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    ...
    this.listView= (ListView) super.getActivity().findViewById(R.id.fragment01_listView);
    ...
    this.arrayAdapter_string= new ArrayAdapter<String>(super.getActivity(), R.layout.dispositivo_ble_item, R.id.fragment01_item_textView_titulo);
    this.listView.setAdapter(this.arrayAdapter_string);
}


@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
    ...
    super.getActivity().runOnUiThread(new RefreshListView(device));
}


private class RefreshListView implements Runnable
{
    private BluetoothDevice bluetoothDevice;

    public RefreshListView(BluetoothDevice bluetoothDevice)
    {
        this.bluetoothDevice= bluetoothDevice;
    }

    @Override
    public void run()
    {
        Fragment01.this.arrayAdapter_string.add(new String(bluetoothDevice.toString()));
        Fragment01.this.arrayAdapter_string.notifyDataSetChanged();
    }
}

Dann begann die ListView dynamisch mit der Mac-Adresse der gefundenen Geräte zu füllen.

jsanmarb
quelle
0

Ich denke, es hängt davon ab, was Sie unter Aktualisieren verstehen. Meinen Sie damit, dass die GUI-Anzeige aktualisiert werden soll, oder meinen Sie, dass die untergeordneten Ansichten so aktualisiert werden sollen, dass Sie programmgesteuert getChildAt (int) aufrufen und die Ansicht abrufen können, die dem Adapter entspricht.

Wenn Sie möchten, dass die GUI-Anzeige aktualisiert wird, rufen Sie notifyDataSetChanged () auf dem Adapter auf. Die GUI wird beim nächsten Neuzeichnen aktualisiert.

Wenn Sie getChildAt (int) aufrufen und eine Ansicht abrufen möchten, die den Inhalt des Adapters widerspiegelt, rufen Sie layoutChildren () auf. Dadurch wird die untergeordnete Ansicht aus den Adapterdaten rekonstruiert.

benommen
quelle
0

Ich hatte eine ArrayList, die ich in einer Listenansicht anzeigen wollte. ArrayList enthielt Elemente aus MySQL. Ich habe die onRefresh-Methode überschrieben und bei dieser Methode tablelayout.removeAllViews () verwendet. und wiederholte dann den Vorgang zum erneuten Abrufen von Daten aus der Datenbank. Stellen Sie jedoch vorher sicher, dass Sie Ihre ArrayList oder eine andere Datenstruktur löschen. Andernfalls werden neue Daten an die alte angehängt.

Kshitij G.
quelle
0

Wenn Sie die UI-Listenansicht von einem Dienst aus aktualisieren möchten, machen Sie den Adapter in Ihrer Hauptaktivität statisch und gehen Sie folgendermaßen vor:

@Override
public void onDestroy() {
    if (MainActivity.isInFront == true) {
        if (MainActivity.adapter != null) {
            MainActivity.adapter.notifyDataSetChanged();
        }

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    
Mayank Saini
quelle
0

Wenn Sie mit dem Android - Führungslinien werden und Sie verwenden die ContentProvidersDaten von zu erhalten Databaseund Sie die Anzeige in der ListViewVerwendung der CursorLoaderund CursorAdapters, dann sind Sie alle Änderungen an den zugehörigen Daten werden automatisch in der Listview widerspiegeln.

Ihre getContext().getContentResolver().notifyChange(uri, null);auf dem Cursor in der ContentProviderwird ausreichen, um die Änderungen widerzuspiegeln. Keine zusätzliche Umgehung erforderlich.

Wenn Sie jedoch nicht alle verwenden, müssen Sie dem Adapter mitteilen, wann sich das Dataset ändert. Außerdem müssen Sie Ihren Datensatz neu füllen / neu laden (z. B. Liste) und dann notifyDataSetChanged()den Adapter aufrufen .

notifyDataSetChanged()funktioniert nicht, wenn es keine Änderungen im Datset gibt. Hier ist der Kommentar über der Methode in docs-

/**
 * Notifies the attached observers that the underlying data has been changed
 * and any View reflecting the data set should refresh itself.
 */
Sanjeet A.
quelle
0

Ich konnte notifyDataSetChanged nur erhalten, indem ich neue Adapterdaten abrief, dann den Adapter für die Listenansicht zurücksetzte und den Aufruf folgendermaßen tätigte:

    expandableAdapter = baseFragmentParent.setupEXLVAdapter();
    baseFragmentParent.setAdapter(expandableAdapter);
    expandableAdapter.notifyDataSetChanged(); 
Kristy Welsh
quelle
0

auf andere Option ist onWindowFocusChangedMethode, aber sicher, es ist sensibel und benötigt eine zusätzliche Codierung für wen interessiert

 override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)

       // some controls needed
        programList = usersDBHelper.readProgram(model.title!!)
        notesAdapter = DailyAdapter(this, programList)
        notesAdapter.notifyDataSetChanged()
        listview_act_daily.adapter = notesAdapter
    }
Sam
quelle
0

Angenommen, Sie haben eine Liste an Ihren Adapter übergeben.
Verwenden:

list.getAdapter().notifyDataSetChanged()

um deine Liste zu aktualisieren.

Mahdi-Malv
quelle
0

Wenn ich hier über mein Szenario gesprochen habe, funktioniert keine der oben genannten Antworten, da ich eine Aktivität hatte, die eine Liste von Datenbankwerten zusammen mit einer Löschtaste anzeigt, und wenn eine Löschtaste gedrückt wird, wollte ich dieses Element aus der Liste löschen.

Das Coole war, ich habe keine Recycler-Ansicht verwendet, sondern eine einfache Listenansicht und diese in der Adapterklasse initialisierte Listenansicht. Das Aufrufen von notifyDataSetChanged()wird also innerhalb der Adapterklasse und sogar in der Aktivitätsklasse, in der das Adapterobjekt initialisiert wird, nichts tun, da sich die Löschmethode in der Adapterklasse befand.

Die Lösung bestand also darin, das Objekt in der Adapterklassenmethode aus dem Adapter zu entfernen getView(um nur dieses bestimmte Objekt zu löschen, aber wenn Sie alle löschen möchten, rufen Sie auf clear()).

Um eine Vorstellung davon zu bekommen, wie mein Code aussah,

public class WordAdapter extends ArrayAdapter<Word> {
  Context context;

  public WordAdapter(Activity context, ArrayList<Word> words) {}
    //.......

    @NonNull
    @Override
    public View getView(final int position, View convertView, ViewGroup group) {
      //.......
     ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
     deleteBt.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (vocabDb.deleteWord(currentWord.id)) {
                //.....
             } else{
                //.....
             }
             remove(getItem(position)); // <---- here is the trick ---<
             //clear() // if you want to clear everything
         }
    });
 //....

Hinweis: Hier remove()und getItem()Methoden werden von der Adapterklasse geerbt.

  • remove() - um das bestimmte Element zu entfernen, auf das geklickt wird
  • getItem(position) - soll das Element (hier ist das mein Word-Objekt, das ich zur Liste hinzugefügt habe) von der angeklickten Position abrufen.

So setze ich den Adapter auf die Listenansicht in der Aktivitätsklasse,

    ArrayList<Word> wordList = new ArrayList();
    WordAdapter adapter = new WordAdapter(this, wordList);

    ListView list_view = (ListView) findViewById(R.id.activity_view_words);
    list_view.setAdapter(adapter);
Blasanka
quelle
-1

Am einfachsten ist es, einfach einen neuen Adaper zu erstellen und den alten fallen zu lassen:

myListView.setAdapter(new MyListAdapter(...));
user1712200
quelle
Dies verbraucht mehr Speicher.
Spieler1
Der Müll wird gesammelt
Benutzer1712200