1

notifyDatasetChanged() を再度呼び出すまで、getView 呼び出しを停止するにはどうすればよいですか?

私の問題:

textchange でアダプタをフィルタリングするテキストフィールドがあります。テキストを頻繁に変更しすぎると、ArrayIndexOutOfBoundsException が発生します。これは、セカンダリ フィルタリング操作が既に実行されている間でも、もちろん getView がアダプタのリストにアクセスしているためです。

したがって、ATM は次のようになります。

  1. バックグラウンドでフィルター + notifyDatasetChanged
  2. GetView が複数回呼び出されました
  3. 次のフィルターが処理されている間、GetView は最初のフィルターのためにバックグラウンドでまだ呼び出されています。しかし、GetView はリスト アクセスのため例外を取得します (フィルタリング操作はリストを変更します)。したがって、GetView 呼び出しを停止し、特定のフィルター操作を開始したいと考えています。

編集:

フィルター スレッドがアクティブであることがわかったら、すぐに getview から戻ることを考えていましたか?

編集:

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

Filter を拡張したフィルタです。m_Items と m_AllItems がアダプターで使用されます (最初の項目にはフィルター処理されたものが含まれ、2 番目にはフィルター処理されていない項目が含まれます)。ご覧のとおり、performFiltering() で変更されていません。また、filterLock はサイズ 1 のセマフォであるため、2 つのフィルタリング操作が同時に行われることはありません。

EDIT2:

また、私の onTextChanged では、アダプターを変更しないことを保証できます。また、performFiltering() から呼び出される filter() メソッドでも変更しません。

4

1 に答える 1

0

UIスレッドからではなくアダプターに変更を加えると、問題が発生します。すべてのアダプターの変更を UI スレッドに投稿しても、すべてが次々に発生するため、発生しません。

負荷の高い処理は別のスレッドで行うことができますが、アダプターに変更を加えたい場合は、ハンドラーまたは を使用して UI スレッドで行う必要があります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、アダプターのアイテムリストを変更して を呼び出すUI スレッド a に投稿しますnotifyDataSetChanged()。これは、ListView と競合しないため、アダプタ。

于 2013-03-26T20:24:16.860 に答える