Як оновити перегляд списку Android?


436

Як оновити Android ListViewпісля додавання / видалення динамічних даних?


3
Якщо інші рішення не працюють, спробуйте refreshDravableState. Реквізит до stackoverflow.com/questions/5186359/…
Едвін Еванс

Може бути допоможе вам, stackoverflow.com/a/17333384/596555
boiledwater

Приклад тут tutorialkart.com/kotlin-android/… може допомогти вам.
Mallikarjun M

Відповіді:


530

Коли ви змінили дані в цьому адаптері, зателефонуйте notifyDataSetChanged()на свій Adapterоб'єкт.

Деякі додаткові відомості про те, як / коли телефонувати, notifyDataSetChanged()можна переглянути у цьому відео вводу / виводу Google .


24
Ви повинні запустити його на потоці інтерфейсу користувача. Створіть обробник у потоці користувальницького інтерфейсу, а потім опублікуйте до нього доступ
Кирило Кулаков

11
Ще раз: notifyDataSetChanged () не працює принаймні не для практик використання, які рекомендуються (читати не застаріло). Якщо ви використовуєте listview, адаптер курсору та постачальник вмісту, ви можете спробувати щось у рядках: gettLoaderManager (). RestartLoader (). Дивіться: stackoverflow.com/a/19657500/1087411 Я хотів би побачити хоча б деяку документацію щодо notifyDataSetChanged (). Багато в андроїді залишається для тестування чорної скриньки.
Андерсон

Якщо notifyDataSetChanged не працює, ви є тим, хто робить це неправильно
zdarsky.peter

4
notifyDataSetChanged не завжди працює. Я не впевнений, чому це суперечить. Іноді вам доведеться зателефонувати listView.setAdapter (адаптер), щоб очистити старі представлення даних. Дивіться також: stackoverflow.com/a/16261588/153275

1
Мені ніколи не вдалося отримати сповіщенняDataSetChanged працює. Я чітко бачив, що колекція, яку я подаю на адаптер, змінилася (елементи було видалено), але notifyDataSetChanged ніколи нічого не робив. Не впевнені, чи просто цей метод порушено?
byemute

204

Також ви можете використовувати це:

myListView.invalidateViews();

22
Це правильна відповідь, якщо потрібно лише ЗНОВИТИ подання. Наприклад, після входу користувача, якому потрібно розкрити більше інформації або параметрів у кожному перегляді listView. Це мені потрібно було зробити, тому я дав підсумкове голосування. Якщо основні дані змінюються, можливо, краща ідея використовувати notifyDataSetChanged ().
SBerg413

Насправді invalidateViews()у наборах вихідного коду, mDataChanged = true;тому я не впевнений, що це призведе до кращої продуктивності порівняно зnotifyDataSetChanged()
vovahost

Ти врятував мені день, чувак!
oskarko

ви можете прийняти тип списку, який є "спостережуваним списком", не потрібно повідомлятинадані змінили
Priya

153

Будь ласка , ігноруйте все invalidate(), invalidateViews(),requestLayout() , ... відповіді на це питання.

Правильна річ (і, на щастя, також зазначена як правильна відповідь) - зателефонувати notifyDataSetChanged()на адаптер .

Вирішення проблем

Якщо дзвінок notifyDataSetChanged()не працює, всі методи компонування також не допоможуть. Повірте, це ListViewбуло належним чином оновлено. Якщо ви не знайдете різницю, вам потрібно перевірити, звідки беруться дані у вашому адаптері.

Якщо це лише колекція, яку ви зберігаєте в пам’яті, перевірте, що ви фактично видалили або додали предмети до колекції, перш ніж викликати notifyDataSetChanged().

Якщо ви працюєте з базою даних або сервісом резервного сервісу, вам доведеться викликати метод для повторного отримання інформації (або маніпулювання даними в пам'яті), перш ніж викликати notifyDataSetChanged().

Річ у тім, що це notifyDataSetChangedпрацює лише в тому випадку, якщо набір даних змінився. Тож це є місце, де слід знайти, якщо не знайдеш змін. Налагоджуйте при необхідності.

ArrayAdapter проти BaseAdapter

Я виявив, що робота з адаптером, який дозволяє керувати колекцією, як BaseAdapter, працює краще. Деякі адаптери, як-от ArrayAdapter, вже керують власною колекцією, що ускладнює доступ до належної колекції для оновлень. Це дійсно просто зайвий шар складності в більшості випадків.

Нитка UI

Це правда, що це потрібно викликати з потоку інтерфейсу користувача. Інші відповіді мають приклади, як цього досягти. Однак це потрібно лише в тому випадку, якщо ви працюєте над цією інформацією за межами потоку інтерфейсу користувача. Це з сервісу чи потоку, що не використовується в інтерфейсі. У простих випадках ви будете оновлювати свої дані натисканням кнопки або іншою діяльністю / фрагментом. Отже, всередині потоку інтерфейсу користувача. Не потрібно завжди з'являти цей runOnUiTrhead в.

Короткий приклад проекту

Його можна знайти на веб- сайті https://github.com/hanscappelle/so-2250770.git . Просто клонуйте та відкрийте проект в Android Studio (gradle). Цей проект має будівлю MainAcibility aListView з усіма випадковими даними. Цей список можна оновити за допомогою меню дій.

Реалізація адаптера, створена для цього прикладу ModelObject, розкриває збір даних

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

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

Більше інформації

Ще один приємний пост про силу listViews можна знайти тут: http://www.vogella.com/articles/AndroidListView/article.html


16
ви помиляєтеся. notifyDataSetChanged () не працював для мене, але invalidateViews () зробив це правильно.
бабай

6
У мене виникла проблема, коли фактичні елементи у списку не змінюються, наприклад, однакова кількість елементів. Але проблема полягає в тому, що спосіб їх подання потребує зміни. Це означає, що код мого адаптера для створення інтерфейсу повинен запуститися знову, а потім правильно приховати якийсь елемент у рядах списку. notifyDataSetChanged () не працює ...
Sven Haiges

9
Ця відповідь мені справді допомогла. Я зберігав масив у пам'яті з певних причин. Щоб виправити це, я зараз телефоную adapter.clear(), а adapter.addAll(Array<T>)перед тим, як зателефонуватиnotifyDataSetChanged()
Майклу Дефілліпсу

2
@hcpl, як мені зателефонувати notifyDataSetChanged, якщо я перебуваю в OnClickListener адаптера для CheckBox? InvalidateViews зараз виконує роботу. Чому InvalidateViews невірний метод для виклику?
викрадено

1
Мені ніколи не вдалося отримати сповіщенняDataSetChanged працює. Я чітко бачив, що колекція, яку я подаю на адаптер, змінилася (елементи було видалено), але notifyDataSetChanged ніколи нічого не робив. Не впевнені, чи просто цей метод порушено?
byemute

42

Виконувати дзвінки можна коли завгодно:

runOnUiThread(run);

OnCreate(), Ви встановлюєте поток, який можна виконати:

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

1
Працює також у моєму випадку, коли мені потрібно оновити перегляд списку на основі даних, що надходять із з'єднання TCP (з потоку "nonUI"). Єдиний спосіб переробляти список - це очистити та повторно додати всі елементи ArrayList. У будь-якому випадку, якщо ви вже в потоці інтерфейсу користувача, вам не потрібно викликати код за допомогою runOnUiThread()функції.
Андре

Дякую! Це працює для мене. Для всіх людей, які хочуть запустити це з фрагмента, слід скористатися getActivity (). RunOnUiThread (новий Runnable ..., щоб переконатися, що код запускається на потоці інтерфейсу
codingpuss

Я не бачу мети run = new Runnable()і просто надав своїй функції public void refreshUIThread()метод, який моделює ваш run()метод (який теж працює).
T.Woody

11

У мене виникли деякі проблеми з динамічним оновленням перегляду списків.

Зателефонуйте notifyDataSetChanged () на адаптері.

Деякі додаткові характеристики щодо того, як / коли зателефонувати notifyDataSetChanged (), можна переглянути у цьому відео вводу / виводу Google.

notifyDataSetChanged () не працював належним чином у моєму випадку [я назвав notifyDataSetChanged з іншого класу]. Так само у випадку, коли я редагував ListView у запущеній діяльності (Thread). Це відео завдяки Крістоферу дало остаточну підказку.

У своєму другому класі я використовував

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

щоб отримати доступ до оновлення () з моєї активності. Це оновлення включає

myAdapter.notifyDataSetChanged();

сказати Адаптеру оновити вигляд. Наскільки добре я працював.



5

якщо ви все ще не задоволені ListView Refreshment, ви можете подивитися цей фрагмент, це для завантаження listView з БД. Насправді, вам потрібно просто перезавантажити ListView після виконання будь-якої операції CRUD, це не найкращий спосіб код, але він оновить ListView за вашим бажанням ..

Це працює для мене .... якщо ви знайдете краще рішення, будь ласка, поділіться ...

.......
......
виконайте свої CRUD-операції ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Принесіть DB_resulta і додайте його до списку як його вміст ....
                                            ls2.setAdapter (новий ArrayAdapter (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
                                            DBAdapter.close ();

2

Рішення, запропоновані людьми в цій публікації, працюють або не в основному залежать від версії Android на вашому пристрої. Для прикладу, щоб використовувати метод AddAll, ви повинні поставити android: minSdkVersion = "10" у своєму пристрої Android.

Щоб вирішити ці питання для всіх пристроїв, я створив свій власний метод у своєму адаптері і використовую всередині спадковий метод ArrayAdapter метод додавання та видалення, який без проблем оновлює ваші дані.

Мій код: Використовуючи власний клас даних RaceResult, ви використовуєте власну модель даних.

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

РезультатиGp.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

Якщо ви хочете зберегти своє місце прокрутки, коли ви оновите, і ви можете це зробити:

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

Докладнішу інформацію див. У Android ListView: Зберігайте позицію прокрутки під час оновлення .


1

Просто використовуйте myArrayList.remove(position);всередині слухача:

  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

Потрібно використовувати один об'єкт у цьому списку, на якому ви надуваєте дані ListView. Якщо посилання є зміною, то вона не notifyDataSetChanged()працює. Коли ви видаляєте елементи зі списку списку, також видаляйте їх зі списку, який ви використовуєте, чи це ArrayList <> чи щось інше, а потім виклик notifyDataSetChanged()на об'єкт класу адаптерів.

Отже, ось, як я впорався з цим у своєму адаптері, дивіться нижче

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
ваше пояснення недооцінене, але це дійсно дає мені розуміння щодо довідки про arraylist. дякую
Авраам Путра Пракаса

0

Видаливши дані зі списку списку, вам потрібно зателефонувати refreshDrawableState(). Ось приклад:

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

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

і deleteContactметод у DatabaseHelperкласі буде дещо схожим

public boolean deleteContact(long rowId) {

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

}

0

Мені не вдалося змусити notifyDataSetChanged () працювати над оновленням мого SimpleAdapter, тому замість цього я спробував спочатку видалити всі представлення, які були прикріплені до батьківського макета за допомогою RemoveAllViews (), потім додав ListView, і це спрацювало, дозволивши мені оновити оновлення Інтерфейс користувача:

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

Для мене після зміни інформації в sql базі даних нічого не може оновити перегляд списку (щоб бути конкретним переглядом списку), тому якщо notifyDataSetChanged () не допоможе, ви можете спробувати очистити свій список спочатку та додати його знову після цього дзвінка notifyDataSetChanged (). Наприклад

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

Сподіваюся, це має сенс для вас.



0

Я був таким самим, коли у фрагменті я хотів заповнити ListView (в одному TextView) з mac-адресою BLE-пристроїв, сканованих протягом певного часу.

Що я зробив:

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

Потім ListView почав динамічно заповнюватися мак-адресою знайдених пристроїв.


0

Я думаю, це залежить від того, що ви розумієте під оновленням. Ви маєте на увазі, що дисплей GUI повинен бути оновлений, або ви маєте на увазі, що дочірні подання повинні бути оновлені таким чином, щоб ви могли програмно зателефонувати на getChildAt (int) та отримати вигляд, відповідний тому, що знаходиться в адаптері.

Якщо ви хочете оновити дисплей GUI, то зателефонуйте notifyDataSetChanged () на адаптер. GUI буде оновлений при наступному перекроюванні.

Якщо ви хочете мати можливість зателефонувати на getChildAt (int) та отримати вигляд, який відображає те, що є у адаптері, тоді зателефонуйте до layoutChildren (). Це призведе до реконструкції дочірнього виду з даних адаптера.


0

У мене був ArrayList, який я хотів відобразити в перегляді списку. ArrayList містив елементи з mysql. Я перекрив метод onRefresh і в цьому методі я використав tablelayout.removeAllViews (); а потім повторив процес отримання даних знову з бази даних. Але перед цим переконайтесь, що очистите ваш ArrayList або будь-яку структуру даних, або нові дані будуть додані до старих.


0

Якщо ви хочете оновити перегляд списку користувальницького інтерфейсу в сервісі, то перетворіть адаптер статичним у свою Основну діяльність та виконайте це:

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

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

0

Якщо ви збираєтесь керівними лініями для Android і ви використовуєте ContentProvidersдля отримання даних, Databaseі ви відображаєте їх у програмі ListView" CursorLoaderі" CursorAdapters, то всі зміни пов’язаних даних автоматично відображатимуться у ListView.

Вашого getContext().getContentResolver().notifyChange(uri, null);курсору у ContentProviderзаповіті буде достатньо, щоб відобразити зміни. Не потрібно додаткової роботи.

Але коли ви не використовуєте все це, вам потрібно повідомити адаптер, коли набір даних змінюється. Також вам потрібно повторно заповнити / перезавантажити свій набір даних (скажіть список), а потім вам потрібно зателефонувати notifyDataSetChanged()на адаптер.

notifyDataSetChanged()не буде працювати, якщо в датсеті немає змін. Ось коментар вище методу в документах-

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

0

Мені вдалося отримати тільки notifyDataSetChanged, лише отримавши нові дані адаптера, потім скинувши адаптер для перегляду списку, а потім здійснив виклик так:

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

0

в іншому варіанті - onWindowFocusChangedметод, але впевнений, що він чутливий і потребує додаткового кодування, для кого це цікаво

 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

Подумайте, що ви передали список своєму адаптеру.
Використання:

list.getAdapter().notifyDataSetChanged()

щоб оновити список.


0

Якщо я говорив про свій сценарій тут, не вказані вище відповіді не спрацюють, оскільки у мене була активність, яка показує список значень db разом із кнопкою видалення, і коли натиснути кнопку видалення, я хотів видалити цей елемент зі списку.

Прикольне те, що я не використовував перегляд рециркулятора, а простий перелік списків і цей перегляд списку, ініціалізований у класі адаптерів. Отже, виклик notifyDataSetChanged()волі нічого не зробить усередині класу адаптерів і навіть у класі активності, де об'єкт адаптера ініціалізований, оскільки метод видалення був у класі адаптера.

Таким чином, рішення полягало в тому, щоб видалити об'єкт з адаптера getViewметодом класу адаптерів (видалити лише цей конкретний об'єкт, але якщо ви хочете видалити всі, зателефонуйтеclear() ).

Вам зрозуміти, як виглядав мій код,

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

Примітка: тут remove()і getItem()методи успадковуються від класу Adapter.

  • remove() - для видалення конкретного елемента, який натиснув
  • getItem(position) - це отримати елемент (ось, це мій об’єкт Word, який я додав до списку) з позиції клацання.

Ось так я встановив адаптер для перегляду списку в класі активності,

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.