2012-03-13 4 views
17

Próbuję zaktualizować ListView z całkowicie nową ArrayList. Dla API 11 działa wspaniale przy użyciu metody addAll (...), ale nie jest dostępna dla wcześniejszych API. Nie mogę wymyślić, jak zaktualizować całą listę dla starszych wersji.ListViews - jak korzystać z funkcji ArrayAdapter.addAll() przed API 11?

ArrayAdapter<String> textList = new ArrayAdapter<String>(listener, R.layout.list_item, stringList); 
listener.setListAdapter(textList); 

Później ...

textList.clear(); 
textList.addAll(stringList); <--- works fine for Android 3.0 (API Level 11) and beyond, but not before. 

Jak się za to zabrać, zanim AddAll() została wprowadzona w API 11? Dzięki.

Odpowiedz

11

Najprostszym sposobem jest uniknięcie użycia ArrayAdapter.addAll() i ArrayAdapter.add() w pętli, jak zasugerował idiottiger w swojej odpowiedzi.

Jeśli chcesz użyć ArrayAdapter.addAll(), krótka odpowiedź to Zrób to sam. Sprawdź źródło android.widget.ArrayAdapter here, rzeczywista implementacja jest znacznie prostsza niż Ci się wydawało. istnieje wiele alternatyw aby to osiągnąć, na przykład:

  • Opcja 1: Wdrożenie jesteś właścicielem ArrayAdapter rozciąga android.widget.BaseAdapter, masz pełną kontrolę nad prywatnym instancja zmiennej oraz sposobu i można określić dowolnej metody twój chce w twojej własnej implementacji . istnieje wiele samouczków w Internecie, które opisują, jak utworzyć niestandardową kartę, taką jak here i here.
  • Wariant 2: Wdrożenie jesteś właścicielem ArrayAdapter rozciąga android.widget.ArrayAdapter, a następnie dodać wymagane Metoda publiczna AddAll() do własnej realizacji ArrayAdapter, nie masz widoczność na prywatnej członka w android.widget. ArrayAdapter potrzebuje więc użyć istniejącego publicznego interfejsu API ArrayAdapter.add(), aby dodać każdy pojedynczy element w pętli.

Opcja 1 jest preferowana i używana bardzo często, szczególnie w sytuacji, gdy potrzebujesz renderować bardziej złożone niestandardowe elementy interfejsu użytkownika w swoim ListView.

+1

nie byłoby przesadą wdrożyć własną wersję ArrayAdapter z BaseAdapter tylko mieć metodę AddAll? Budowanie go z ArrayAdapter powinno wystarczyć. – josephus

+0

Tak, nadal warto sprawdzić źródło, aby zrozumieć, w jaki sposób adapter jest zaimplementowany w ogóle. – yorkw

+3

jest to trochę niepowiązane, ale sprawdź ten wpis, jeśli używasz Eclipse do tworzenia aplikacji dla systemu Android: http://www.helloandroid.com/content/gold-android-developers-add-aosp-source-code-eclipse- android-sources-plugin – josephus

1

przy użyciu metody textList.add, pętla w liście napisów i jedna po drugiej dodana do listy tekstowej.

1

Można rozszerzyć ArrayAdapter na niestandardową klasę i zaimplementować własną metodę addAll. Byłoby prostsze, gdyby użyć tablicy ArrayList zamiast String, aby można było dodawać dane bez odbudowywania całego zestawu danych.

Edycja: Przypomniałem sobie, że można zmodyfikować dostarczoną tablicę (lub listę tablicową), którą wprowadzono do adaptera, a następnie wywołać metodę notifyDataSetChanged. To powinno zaktualizować twoją listę.

+0

Więc masz na myśli w tym przypadku po prostu zmienić wartości zmiennej 'stringList', a następnie wywołać' textList.notifyDataSetChanged(); '? Próbowałem tego, ale to nie zadziałało. Czy czegoś brakuje? Myślę, że czytałem gdzieś indziej, że ta metoda działa tylko po edycji adaptera '.add' lub' .clear' lub '.remove'? – mattboy

0

natknąłem tego wątku późno, ale następujące rozwiązanie było łatwe do wykonania dla mnie:

public class CustomAdapter extends ArrayAdapter<String>... 

public void setData(ArrayList<String> items) { 
    clear(); 
    setNotifyOnChange(false); 
    if (items != null) { 
     for (String item : items) 
      add(item); 
    } 
    notifyDataSetChanged(); 
} 
19

Oto pełny blok kodu, który wykorzystuje natywne AddAll() dla Android urządzeń z SDK_INT> = 11, i stosuje się obejście pętli urządzeń z poziomu API mniejszej niż 11.

@TargetApi(11) 
public void setData(List<String> data) { 
    clear(); 
    if (data != null) { 
     //If the platform supports it, use addAll, otherwise add in loop 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      addAll(data); 
     } else { 
      for(String item: data) { 
       add(item); 
      } 
     } 
    } 
} 

@TargetApi(11) Adnotacja stosuje ADT 17 w celu stłumienia ostrzeżenia Lint gdy mają <uses-sdk android:minSdkVersion="X"/> w AndroidManifest.xml gdzie X jest mniejsza niż 11.Aby uzyskać więcej informacji, patrz http://tools.android.com/recent/lintapicheck.

+0

Dobra odpowiedź, ale pozwólcie, że podzielę się z Wami doświadczeniem: jeśli użyjecie metody "dodaj" z więcej niż x elementami (ostatecznie ustawiłem ją na 100), tak jak po każdej metodzie "dodawania" będzie " notifydatasetchanged "zadzwoni, nastąpi awaria! – Analizer

+0

@ Analizer z taką ilością rekordów, może lepiej jest użyć 'CursorAdapter'? Zobacz http://stackoverflow.com/questions/21130162/better-to-use-cursor-adapter-or-array-adapter. –

+0

To nie jest zły pomysł, ale nie używam bazy danych, rekordy są pobierane z odpowiedzi JSON z serwera. – Analizer

4

I połączeniu Barbeau i Villarey znajduje się odpowiedź na to, co myślę, że jest to dobre rozwiązanie:

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public void setData(List<String> data) { 
    clear(); 
    if (data != null) { 
     addAll(data); 
    } 
} 


@Override 
@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public void addAll(String... items) { 
    //If the platform supports it, use addAll, otherwise add in loop 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
     super.addAll(items); 
    }else{ 
     for(String item: items){ 
      super.add(item); 
     } 
    } 
} 
3

I zbudowany na innym kodem narodów online i stworzyłem ten. Po prostu użyj tej klasy tam, gdzie jest to potrzebne, zamiast klasy ArrayAdapter.

import android.annotation.SuppressLint; 
import android.content.Context; 
import android.os.Build; 
import android.widget.ArrayAdapter; 

import java.util.Collection; 
import java.util.List; 

public class ArrayAdapterCompat<T> extends ArrayAdapter<T> { 
    public ArrayAdapterCompat(Context context, int resource, List<T> entries) { 
     super(context, resource, entries); 
    } 

    /** 
    * Add all elements in the collection to the end of the adapter. 
    * @param list to add all elements 
    */ 
    @SuppressLint("NewApi") 
    public void addAll(Collection<? extends T> list) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      super.addAll(list); 
     } else { 
      for (T element : list) { 
       super.add(element); 
      } 
     } 
    } 

    /** 
    * Add all elements in the array to the end of the adapter. 
    * @param array to add all elements 
    */ 
    @SuppressLint("NewApi") 
    public void addAll(T... array) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      super.addAll(array); 
     } else { 
      for (T element : array) { 
       super.add(element); 
      } 
     } 
    } 
} 
0

prostu trzeba prostego iteration nad collection z if statement dla version

 //mForecastAdapter.clear(); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      mForecastAdapter.addAll(weekForecast); 
     }else { 
      for (String s : strings) { 
       mForecastAdapter.add(s); 
      } 
     }