ArrayAdapter - 如何停止getView调用?

时间:2013-03-26 20:12:17

标签: java android listview android-arrayadapter indexoutofboundsexception

如何再次调用notifyDatasetChanged()来停止getView调用?

我的问题:

我有一个文本字段,用于过滤textchange上的适配器。如果我经常更改文本,我会得到ArrayIndexOutOfBoundsException,因为当seconding过滤操作已经在运行时,getView当然仍然在访问适配器列表。

所以ATM就是这样的:

  1. 在后台过滤+ notifyDatasetChanged
  2. 多次调用GetView
  3. 在处理下一个过滤器时,由于第一个过滤器,仍在后台调用GetView。但GetView因列表访问(过滤操作更改列表)而异常。所以我想停止GetView调用,然后开始任何给定的过滤器操作。
  4. 编辑:

    如果我看到过滤器线程处于活动状态,我想立即从getview返回?

    编辑:

    确定相关的适配器代码:

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

    这是从Filter扩展的过滤器。 m_Items和m_AllItems用在适配器中(第一个包含过滤的,第二个包含未过滤的)。正如您所看到的那样,它们未在performFiltering()中进行修改。此外,filterLock是1号信号量,因此不会同时进行2次过滤操作。

    EDIT2:

    另外,在我的onTextChanged中,我可以向你保证我不会以任何方式修改那里的适配器,我也不会在performFiltering()调用的filter()方法中

1 个答案:

答案 0 :(得分:0)

更改为适配器而非UI线程是导致问题的原因。 如果你将所有的适配器修改发布到UI线程,它将不会发生,因为它一个接一个地发生。

您可以在不同的线程中执行繁重的处理,但是当您想要将更改放入适配器时,您需要使用处理程序或Activity.runOnUiThread在UI线程上执行此操作。例如:

// 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不知道它。 您需要在项目列表的副本上完成工作,完成后,在UI线程中发布Runnable更改适配器中的项目列表并调用notifyDataSetChanged(),这就是您不会与你的ListView和你的适配器发生冲突。