1

Как остановить вызовы getView, пока я не вызову notifyDatasetChanged() еще раз?ArrayAdapter - как остановить вызовы getView?

Мой вопрос:

У меня есть текстовое поле, который фильтрует адаптер на textchange. Если я слишком часто меняю текст, я получаю ArrayIndexOutOfBoundsException, потому что getView, конечно же, все еще обращается к списку адаптера, когда операция фильтрации посылок уже запущена.

Так ATM это выглядит следующим образом:

  1. фильтр в фоновом режиме + notifyDatasetChanged
  2. GetView вызывается несколько раз
  3. Хотя следующий фильтр обрабатывается, GetView еще называют в фоновом режиме из-за первый фильтр. Но GetView получает исключение из-за доступа к списку (список изменений операции фильтрации). Поэтому я хочу остановить вызовы GetView и THEN запустить любую заданную операцию фильтра.

EDIT:

я думал о возвращении из GetView немедленно, если я вижу фильтр нить активна?

EDIT:

OK соответствующий код адаптера:

@Override 
    protected FilterResults performFiltering(CharSequence constraint) { 
     filterLock.acquireUninterruptibly(); 

     FilterResults r = new FilterResults(); 
     List<T> items = null; 
     m_Filter = constraint; 

     if (constraint == null /* TextUtils.isEmpty(constraint) */) { // AR 
     // auskommentiert 
     // da 
     // ungewünscht 
     items = m_AllItems; 
     } else { 
     items = m_FilteredItems; 
     items.clear(); 

     synchronized (SyncLock) { 
      for (T item : m_AllItems) { 
      if (DynamicArrayAdapter.this.filter(item, constraint)) { 
       items.add(item); 
      } 
      } 
     } 
     } 

     r.values = items; 
     r.count = items.size(); 

     return r; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    protected void publishResults(CharSequence constraint, FilterResults results) { 

     m_Items = (List<T>) results.values; 

     notifyDataSetChanged(); 

     filterLock.release(); 
    } 

Это фильтр, который простирается от фильтра. m_Items и m_AllItems используются в адаптере (первый содержит отфильтрованный, второй - нефильтрованный). Как вы можете видеть, они не изменены в performFiltering(). Также filterLock - это семафор размера 1, так что в это же время не происходит двух фильтрующих операций.

EDIT2:

также, в моем OnTextChanged я могу заверить вас, что я не изменить адаптер есть в любом случае либо, ни я в методе фильтра(), который вызывается из performFiltering()

+2

Вы не должны пытаться остановить вызовы 'getView()', вместо этого вы должны стремиться внедрить лучшую систему фильтрации. Отправьте код, который у вас есть для операции фильтрации. – Luksprog

+0

Вы усложнили операцию фильтрации. Блокировка в основном бесполезна, так как вы не можете одновременно выполнять две операции фильтрации, используя класс «Фильтр». Для доступа к списку данных необходимо выполнить единственную синхронизацию. Кроме того, ** ** копии ** списка не разделяют списки данных. – Luksprog

+0

Я могу поклясться, что я отслеживаю 2 потока через performFiltering, которые были там вместе. Вот почему я это сделал. В любом случае это не повредит Я думаю – cdbeelala89

ответ

0

Выполнение изменений в адаптерах, а не в потоке пользовательского интерфейса, вызывает проблемы. Если вы опубликуете все модификации адаптеров в потоке пользовательского интерфейса, этого не произойдет, потому что все это происходит один за другим.

Вы можете выполнять тяжелую обработку в другом потоке, но если вы хотите внести изменения в адаптер, вам нужно сделать это в потоке пользовательского интерфейса, используя Handler или Activity.runOnUiThread. Например:

// Really heavy filtering process 

runOnUiThread(new Runnable(){ 
      public void run(){ 
       // Change items of Adapter here 
       // Now we are notifying that the data has changed. 
       mAdapter.notifyDataSetChanged(); 
      } 
    }); 

После просмотра кода: Как Luksprog говорят, вы не должны изменять список непосредственно из другого потока, но использовать копию списка. Что происходит, так это то, что ListView принимает список с размером X, но вы уже изменили его на размер Y, и ListView не знал об этом. Вам нужно сделать работу над копией списка ваших товаров, и после того, как вы закончите, опубликуйте в потоке пользовательского интерфейса Runnable, который изменит список элементов в адаптере и вызовет notifyDataSetChanged(), это было бы у вас не будет конфликтов с вами ListView и адаптер.

+0

Я не изменяю m_Items или M_AllItems в потоке. m_FilteredItems, увиденный в моем сообщении, - это уже новый список. – cdbeelala89

Смежные вопросы