Android liste görünümünü nasıl yenileyebilirim?


436

ListViewDinamik veri ekledikten / sildikten sonra bir Android nasıl yenilenir ?


3
Diğer çözümler işe yaramazsa refreshDrawableState'i deneyin. Dikmeler için stackoverflow.com/questions/5186359/...
Edwin Evans


Burada bir örnek tutorialkart.com/kotlin-android/… size yardımcı olabilir.
Mallikarjun E

Yanıtlar:


530

Çağrı notifyDataSetChanged()senin üzerinde Adapterbu bağdaştırıcı verileri modifiye ettik bir kere nesne.

Aranacak nasıl / Bazı ek ayrıntıların notifyDataSetChanged()görülebilir bu Google I / O videosu .


24
UI iş parçacığında çalıştırmalısınız. UI iş parçacığında bir işleyici oluşturun ve ardından Çalıştırılabilir yayınlayın
Kirill Kulakov

11
Bir kez daha: notifyDataSetChanged () en azından önerilen (okumadan kaldırılmamış) kullanım uygulamaları için çalışmaz. Listview, imleç bağdaştırıcısı ve içerik sağlayıcı kullanıyorsanız, satırlar boyunca bir şeyler deneyebilirsiniz: gettLoaderManager (). RestartLoader (). Bkz: stackoverflow.com/a/19657500/1087411 ben notifyDataSetChanged en azından bazı belgelere görmek istiyorum (). Android için çok kara kutu testine bırakılır.
Anderson

NotifyDataSetChanged işe yaramazsa, yanlış yapan
sizsiniz

4
notifyDataSetChanged her zaman çalışmaz. Bunun neden çekiştiğinden emin değilim. Bazen eski görünümleri temizlemek için listView.setAdapter (adaptör) öğesini çağırmanız gerekir. Ayrıca bakınız: stackoverflow.com/a/16261588/153275

1
Asla notDataVetChanged çalışma almak mümkün. Bağdaştırıcıya beslediğim koleksiyonun değiştiğini (öğeler kaldırıldı) açıkça görebiliyordum ama notifyDataSetChanged hiçbir şey yapmadı. Bu yöntemin kırıldığından emin değil misiniz?
byemute

204

Ayrıca bunu kullanabilirsiniz:

myListView.invalidateViews();

22
Bir kişinin yalnızca görünümü yeniden ÇEKMEK gerekiyorsa doğru cevap budur. Örneğin, listView öğesinin her görünümünde daha fazla bilgi veya seçenek ortaya çıkarması gereken bir kullanıcı girişi gerçekleştikten sonra. Yapmam gereken buydu, bu yüzden yukarı oy verdim. Temel alınan veriler değişirse, notifyDataSetChanged () yöntemini kullanmak daha iyi bir fikir olabilir.
SBerg413

Aslında invalidateViews()kaynak kodu kümelerinde mDataChanged = true;bu yüzden karşılaştırıldığında daha iyi performans sonuç verir emin değilimnotifyDataSetChanged()
vovahost

Günümü kurtardın ahbap!
oskarko

"gözlemlenebilir liste" olan bir liste türü alabilirsiniz, bildirmeye gerek yok veri kümesi değişti
Priya

153

Tüm görmezden Lütfen invalidate(), invalidateViews(), requestLayout()bu soruya, ... cevaplar.

Doğru şeyin (ve neyse ki ayrıca sağ yanıt olarak işaretlenebilir) etmektir çağırmak için notifyDataSetChanged()sizin Adaptöründeki .

Sorun giderme

Arama notifyDataSetChanged()işe yaramazsa, tüm düzen yöntemleri de yardımcı olmaz. İnan bana ListViewdüzgün güncellendi. Farkı bulamazsanız, adaptörünüzdeki verilerin nereden geldiğini kontrol etmeniz gerekir.

Bu yalnızca bellekte tuttuğunuz bir koleksiyonsa, çağırmadan önce öğeleri sildiğinizden veya koleksiyona eklediğinizden emin olun notifyDataSetChanged().

Bir veritabanı veya hizmet arka ucuyla çalışıyorsanız, çağırmadan önce bilgileri tekrar almak (veya bellek verilerinde değişiklik yapmak) için yöntemi çağırmanız gerekir notifyDataSetChanged().

Mesele şu ki, notifyDataSetChangedsadece veri kümesi değiştiğinde çalışır. Bu, gelen değişiklikleri bulamazsanız bakmanız gereken yer. Gerekirse hata ayıklayın.

ArrayAdapter vs BaseAdapter

Bir BaseAdapter daha iyi çalışıyor gibi, koleksiyon yönetmenize izin veren bir adaptör ile çalışmanın buldum. ArrayAdapter gibi bazı adaptörler zaten kendi koleksiyonlarını yönetir ve bu da güncellemeler için uygun koleksiyona ulaşmayı zorlaştırır. Çoğu durumda sadece gereksiz bir ekstra zorluk katmanı.

UI İş Parçacığı

Bunun UI iş parçacığından çağrılması gerektiği doğrudur. Diğer cevapların bunu nasıl başaracağına dair örnekleri var. Ancak bu, yalnızca UI iş parçasının dışından bu bilgiler üzerinde çalışıyorsanız gereklidir. Bu, bir hizmetten veya UI olmayan bir iş parçacığından gelir. Basit durumlarda verilerinizi bir düğme tıklaması veya başka bir etkinlik / parçadan güncellersiniz. Hala UI iş parçacığı içinde. Bu runOnUiTrhead'i her zaman patlatmaya gerek yok.

Hızlı Örnek Proje

Https://github.com/hanscappelle/so-2250770.git adresinde bulunabilir . Sadece projeyi klonlayın ve Android Studio'da (derecelendirme) açın. Bu proje, ListViewtüm rasgele verileri içeren bir MainAcitivity binasına sahiptir . Bu liste eylem menüsü kullanılarak yenilenebilir.

Bu örnek ModelObject için oluşturduğum adaptör uygulaması veri toplamayı ortaya koyuyor

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
}

MainActivity'den kod

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();
    }
}

Daha fazla bilgi

ListViews'ın gücü hakkında başka bir güzel yazı burada bulunabilir: http://www.vogella.com/articles/AndroidListView/article.html


16
yanılıyorsun. notifyDataSetChanged () benim için çalışmadı, ancak invalidateViews () doğru yaptı.
babay

6
Listedeki gerçek öğelerin, örneğin aynı miktarda öğenin değişmemesi sorunum var. Ancak sorun şu ki, sunulma biçimlerinin değişmesi gerekiyor. Bu, UI'yi oluşturmak için adaptörünüzün kodunun tekrar çalıştırılması ve ardından liste satırlarındaki bazı öğeleri doğru şekilde gizlemesi gerektiği anlamına gelir. notifyDataSetChanged () çalışmıyor ...
Sven Haiges

9
Bu cevap bana gerçekten yardımcı oldu. Diziyi belirli özelliklerden dolayı bellekte tutuyordum. Düzeltmek için şimdi aradım adapter.clear()ve adapter.addAll(Array<T>)aramadan öncenotifyDataSetChanged()
Michael DePhillips

2
@ hcpl, bir CheckBox için bağdaştırıcının OnClickListener iseniz ben notifyDataSetChanged nasıl çağırmalıyım? invalidateViews şu anda işi yapıyor. Neden invalidateViews çağırmak için yanlış yöntem?
craned

1
Asla notDataVetChanged çalışma almak mümkün. Bağdaştırıcıya beslediğim koleksiyonun değiştiğini (öğeler kaldırıldı) açıkça görebiliyordum ama notifyDataSetChanged hiçbir şey yapmadı. Bu yöntemin kırıldığından emin değil misiniz?
byemute

42

İstediğiniz zaman runnable çağrısı yapın:

runOnUiThread(run);

OnCreate(), çalıştırılabilir ipliğinizi ayarlarsınız:

run = new Runnable() {
    public void run() {
        //reload content
        arraylist.clear();
        arraylist.addAll(db.readAll());
        adapter.notifyDataSetChanged();
        listview.invalidateViews();
        listview.refreshDrawableState();
    }
};

1
Ayrıca bir TCP bağlantısından ("nonUI" iş parçacığı) gelen verilere dayalı bir liste görünümünü güncelleştirmek gerekiyor benim durumumda da çalışıyor. Listenin yeniden çizilmesinin tek yolu, ArrayList öğesinin tüm öğelerini temizlemek ve yeniden eklemekti. Her neyse, zaten UI iş parçacığındaysanız, kodu runOnUiThread()işlev aracılığıyla çağırmanız gerekmez .
Andre

Teşekkürler! Benim için çalışıyor. Bunu bir parçadan çalıştırmak isteyen tüm insanlar için, kodun UI iş parçacığında çalıştığından emin olmak için getActivity (). RunOnUiThread (yeni Runnable ... kullanmalısınız
codingpuss

Amacını görmüyorum run = new Runnable()ve sadece fonksiyonumu public void refreshUIThread()yönteminizi modelleyen bir yöntem verdi run()(ki bu da işe yarıyor).
T.Woody

11

benim liste görünümü dinamik yenileme ile bazı sorunlar var.

Bağdaştırıcınızdaki notifyDataSetChanged () öğesini çağırın.

NotifyDataSetChanged () yönteminin nasıl / ne zaman çağrılacağına ilişkin bazı ek özellikler bu Google I / O videosunda görüntülenebilir.

notifyDataSetChanged () benim durumumda düzgün çalışmadı [Başka bir sınıftan notifyDataSetChanged çağırdı]. Tam olarak ben ListView çalışan Etkinlik (Thread) düzenledi. Christopher sayesinde bu video son ipucunu verdi.

İkinci sınıfta kullandım

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

faaliyetimden update () işlevine erişmek için. Bu güncelleme şunları içerir

myAdapter.notifyDataSetChanged();

Adaptöre görünümü yenilemesini bildirmek için. Söyleyebildiğim kadar iyi çalıştı.



5

ListView Refreshment ile hala memnun değilseniz, bu snippet'e bakabilirsiniz, bu listView'i DB'den yüklemek içindir, Aslında herhangi bir CRUD İşlemini gerçekleştirdikten sonra yapmanız gereken sadece ListView'i yeniden yüklemektir. ancak ListView'i istediğiniz gibi yenileyecektir.

Benim için çalışıyor .... u daha iyi bir çözüm bulursanız, lütfen Paylaşın ...

.......
......
CRUD İşlemlerinizi yapın ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// DB_results'u getirin ve içeriği olarak listeye ekleyin ....
                                            ls2.setAdapter (yeni ArrayAdapter (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
                                            DBAdapter.close ();

2

Bu yazıdaki kişiler tarafından önerilen çözümler, cihazınızın Android sürümüne bağlı olarak çalışır veya işe yaramaz. Örneğin AddAll yöntemini kullanmak için android cihazınıza android: minSdkVersion = "10" koymanız gerekir.

Bu soruları çözmek için adaptörümde kendi yöntemimi oluşturdum ve verileri sorunsuz bir şekilde güncelleyen ArrayAdapter öğesinden ekle ve kaldır yöntemini miras aldım.

Kodum: Kendi veri sınıfımı RaceResult kullanarak, kendi veri modelinizi kullanıyorsunuz.

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!!!

1

Yenileme sırasında kaydırma konumunuzu korumak istiyorsanız ve bunu yapabilirsiniz:

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();
}

Ayrıntılı bilgi için lütfen Android ListView: Yenileme sırasında kaydırma konumunuzu korumaya bakın .


1

Sadece myArrayList.remove(position);bir dinleyicinin içinde kullanın :

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

1

Bu listenin üzerinde şişirmekte olduğunuz verileri içeren tek bir nesne kullanmanız gerekir ListView. Referans değişiyorsa, notifyDataSetChanged()çalışmaz. Öğeleri liste görünümünden sildiğinizde, bunları bir ArrayList <> veya başka bir şey mi, yoksa notifyDataSetChanged()Bağdaştırıcı sınıfınızın Nesnesinde ara olup olmadığını da kullandığınız listeden silin .

İşte burada adaptörümde nasıl yönettiğimi görün aşağıya bakın

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();
}
}

1
açıklamanızın altında kaldınız, ama bu bana gerçekten arraylist referansı hakkında bilgi veriyor. teşekkür ederim
Abraham Putra Prakasa

0

Liste görünümünden veri sildikten sonra aramanız gerekir refreshDrawableState(). İşte örnek:

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

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

ve sınıftaki deleteContactyöntem bir DatabaseHelperşekilde

public boolean deleteContact(long rowId) {

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

}

0

Ben SimpleAdapter güncelleştirmek için çalışmak için notifyDataSetChanged () elde edemedi, bu yüzden ilk önce removeAllViews () kullanarak üst düzenine bağlı tüm görünümleri kaldırmaya çalıştı, sonra ListView ekleyerek ve çalıştı, güncelleştirmek için izin Kullanıcı arayüzü:

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);

0

Benim için sql veritabanındaki bilgileri değiştirdikten sonra hiçbir şey liste görünümünü yenileyemez (belirli genişletilebilir liste görünümü olacak), bu nedenle notifyDataSetChanged () yardımcı olmazsa, önce listenizi temizlemeyi ve o çağrının ardından tekrar notifyDataSetChanged () eklemeyi deneyebilirsiniz. Örneğin

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

Umarım sizin için mantıklıdır.


0

SimpleCursorAdapter kullanırken adaptörde changeCursor (newCursor) çağırabilir.


0

Bir parça halinde, bir ListView (tek bir TextView içinde) bir süre taranan BLE cihazlarının mac adresiyle doldurmak istediğimde aynıydım.

Yaptığım şey şuydu:

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();
    }
}

Sonra ListView dinamik olarak bulunan aygıtların mac adresiyle doldurmaya başladı.


0

Yenileme ile ne demek istediğine bağlı olduğunu düşünüyorum. GUI ekranının yenilenmesi mi, yoksa getChildAt (int) 'yi programlı olarak çağırabileceğiniz ve Bağdaştırıcıdakine karşılık gelen görünümü alabileceğiniz şekilde alt görünümlerin yenilenmesi gerektiği anlamına mı geliyorsunuz?

GUI ekranının yenilenmesini istiyorsanız, bağdaştırıcıdaki notifyDataSetChanged () öğesini çağırın. Bir sonraki yeniden çizildiğinde GUI yenilenecektir.

GetChildAt (int) işlevini çağırabilmek ve bağdaştırıcıda ne olduğunu yansıtan bir görünüm elde etmek istiyorsanız, layoutChildren () işlevini çağırın. Bu, alt görünümün bağdaştırıcı verilerinden yeniden yapılandırılmasına neden olur.


0

Bir liste görünümünde görüntülemek istediğim bir ArrayList vardı. ArrayList mysql öğelerini içeriyordu. OnRefresh yöntemini geçersiz kıldım ve bu yöntemde tablelayout.removeAllViews () kullandım; ve daha sonra veritabanından tekrar veri alma işlemini tekrarladı. Ancak bundan önce ArrayList'inizi veya veri yapısını veya yeni verileri eskisine ekleyeceğinizden emin olun.


0

Bir hizmetten UI liste görünümünü güncellemek istiyorsanız, Ana etkinliğinizde bağdaştırıcıyı statik hale getirin ve bunu yapın:

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

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    

0

Android kılavuz çizgileri ile gidiyoruz ve ContentProvidersveri almak Databaseiçin ListViewkullanıyorsanız CursorLoaderve kullanarak ve görüntülüyor ve CursorAdapterssonra ilgili verilerde tüm değişiklikler otomatik olarak ListView yansıtılır.

Sizin getContext().getContentResolver().notifyChange(uri, null);imleç üzerinde ContentProviderdeğişiklikleri yansıtmak için yeterli olacaktır. Etrafında ekstra çalışma gerek yok.

Ancak bunların hepsini kullanmadığınızda, veri kümesinin değiştiğinde adaptöre söylemeniz gerekir. Ayrıca veri kümenizi yeniden doldurmanız / yeniden yüklemeniz gerekir (liste diyelim) ve daha sonra notifyDataSetChanged()adaptörü çağırmanız gerekir .

notifyDataSetChanged()veri kümesinde değişiklik yoksa işe yaramaz. Burada dokümanlar-

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

0

Ben sadece yeni adaptör veri alarak, daha sonra liste görünümü için bağdaştırıcı sıfırlayarak, sonra böyle arama yaparak notifyDataSetChanged elde edebildi:

    expandableAdapter = baseFragmentParent.setupEXLVAdapter();
    baseFragmentParent.setAdapter(expandableAdapter);
    expandableAdapter.notifyDataSetChanged(); 

0

diğer seçenek onWindowFocusChangedyöntemdir, ancak hassas olduğundan ve ilgilendiği için ekstra kodlamaya ihtiyaç duyduğundan emin olun.

 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
    }

0

Bağdaştırıcınıza bir liste ilettiğinizi düşünün.
kullanın:

list.getAdapter().notifyDataSetChanged()

listenizi güncellemek için.


0

Burada senaryom hakkında konuştuysam, silme düğmesiyle birlikte db değerleri listesini gösteren bir aktiviteye sahip olduğum ve silme düğmesine basıldığında yukarıdaki yanıtların hiçbiri işe yaramaz, listeden bu öğeyi silmek istedim.

Harika bir şey, geri dönüşümcü görünümü değil, basit bir liste görünümü ve adaptör sınıfında başlatılan bu liste görünümü oldu. Bu nedenle, notifyDataSetChanged()will uyarlaması, adaptör sınıfının içinde ve hatta delete yönteminin adaptör sınıfında olduğu için adaptör nesnesinin başlatıldığı etkinlik sınıfında hiçbir şey yapmaz.

Bu nedenle, çözüm, bağdaştırıcı sınıfı getViewyönteminde nesneyi bağdaştırıcıdan kaldırmaktı (yalnızca belirli bir nesneyi silmek, ancak tümünü silmek istiyorsanız arayın clear()).

Size bir fikir vermeniz için kodum neye benziyordu,

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
         }
    });
 //....

Not: burada remove()ve getItem()yöntemler Adapter sınıfından miras alınır.

  • remove() - tıklanan belirli öğeyi kaldırmak için
  • getItem(position) - tıklanan konumdan (buraya, listeye eklediğim Word nesnesim) öğeyi almaktır.

Bağdaştırıcıyı etkinlik sınıfındaki liste görünümüne böyle ayarlıyorum,

    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);

-1

En kolayı sadece yeni bir Adaper yapmak ve eskisini bırakmak:

myListView.setAdapter(new MyListAdapter(...));

Bu daha fazla bellek tüketir.
Oyuncu1

çöp toplanacak
user1712200
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.