2016-12-06 10 views
0

私はちょっと困惑しています。私はTextWatcher afterTextChanged(Editable s)メソッドを使用して、ユーザーが入力したテキストを検索し、リストの単語の1つを入力した場合は検出し、そうであればその位置にスパンを追加します。AsyncTask in Custom EditText

私がAfterTextChangedで直接実装しようとしたとき、テキストが拡大して特定の単語にまたがることが困難になり、AsynkTaskクラスで作業を移動しました。ここではクラスがある:

class SearchText extends AsyncTask<String, String, Void> { 
    private String match = "(\\d)?(([\\p{Alnum}\\p{Punct}])+?) ([0-9]+?)\\b:([0-9]+?)(, ([0-9]+?))?(-([0-9]+?))?\\b"; 
    private Editable s; 

    SearchText(Editable s) { 
     this.s = s; 
    } 

    @Override 
    protected Void doInBackground(String... params) { 
     Matcher m = Pattern.compile(match).matcher(s); 
     while (m.find()) { 
      Reference reference = new Reference(m.group(9)); 
      if (booksList.contains(m.group(2)) && mListener.check(reference)) { 

       BooksSpan booksSpan = new BooksSpan("1"); 
       try { 
        s.setSpan(booksSpan, m.start(), m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
       } catch (Exception e) { 
        Log.e("error", e.getMessage()); 
       } 
      } 
     } 
     return null; 
    } 
} 

s.setSpan(booksSpan, m.start(), m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);私は本当に速く入力すると、ランダムな言葉のように、それは私を与える:

Only the original thread that created a view hierarchy can touch its views.

なぜこれがちょうど時々ありますか?編集可能なのはビューではありません。私は何が欠けていますか?

+0

なぜこのようなことが起こるのかわかりません。しかし、AsyncTaskを使うときは、UIを操作するために 'onPostExecute()'を使うべきです。 – AlbAtNf

+0

編集可能なUIの仕組みは? –

+0

完全なスタックトレースを表示します。 –

答えて

1

私は、次の単純化されたコードでテスト:

class SearchText extends AsyncTask<String, String, Void> { 
    private String match = "t"; 
    private Editable s; 

    SearchText(Editable s) { 
     this.s = s; 
    } 

    @Override 
    protected Void doInBackground(String... params) { 
     Matcher m = Pattern.compile(match).matcher(s); 
     while (m.find()) { 
      try { 
       s.replace(m.start(), m.end(), "A"); 
      } catch (Exception e) { 
       Log.e("error", e.getMessage()); 
      } 
     } 
     return null; 
    } 
} 

私は本当に速いと入力した場合、あなたが説明するように、例外が、スローされます。 私は次のようにコードを変更すると、それは問題なく動作します。

class SearchText extends AsyncTask<String, String, Map<Integer, Integer>> { 
    private String match = "t"; 
    private Editable s; 

    SearchText(Editable s) { 
     this.s = s; 
    } 

    @Override 
    protected Map<Integer, Integer> doInBackground(String... params) { 
     Matcher m = Pattern.compile(match).matcher(s); 
     Map<Integer, Integer> map = new HashMap<>(); 
     while (m.find()) { 
      map.put(m.start(), m.end()); 
     } 
     return map; 
    } 

    @Override 
    protected void onPostExecute(Map<Integer, Integer> result) { 
     for (Integer i : result.keySet()) { 
      try { 
       s.replace(i, result.get(i), "AAAA"); 
      } catch (Exception e) { 
       Log.e("error", e.getMessage()); 
      } 
     } 
    } 
} 

だから、解決策はonPostExecuteで編集の操作を実行することです。

+0

onPostExecuteはUIで実行されます。テキストが大きくなると速度が低下するため、 –

+0

の解決策があります。非同期は500ミルあたり最大1回と呼ばれ、 –

+0

私は私たちの答えを組み合わせて、私は良い妥協であると思います。私はonPostExecuteの変更を実行しますが、asynkは1000 milisごとに一度しか呼び出されませんので、ありがとう –

関連する問題