2017-06-05 19 views
0

AutoCompleteTextViewのテキストを受け取るAndroidアプリで検索機能を実装しようとしていますが、最後の1.5秒間に変更が加えられていないのを待って検索を示します結果。このため私はTextWatcherクラスを使用します。UIフリーズのない計算が完了するまで待つ

しかし、この動作を実装しようとする私の試みは、UIスレッド自体(runOnUIThread経由)または前に呼び出されたLooper.prepare()のスレッドでのみ許可されているいくつかの関数で問題になりました。

追加の文字を入力したり削除したり、検索結果を表示したり、開始アクティビティにリロードしたりすると、アプリがランダムにクラッシュします。

以下は、私がHandlerを使用している私の最近の試みの単純なレクリエーションです。

search.getResultsは長い計算とmatchesArrayAdapterWithSpaceFilterを作成delayableAdapterCreationを満たさなければならない配列です。この時点で

public class SearchFragment extends Fragment { 

    public final static int MAX_NUMBER_OF_SUGGESTIONS = 4; // only show a max of 4 suggestions if more were found 
    public final static int SEARCH_CHAR_AMOUNT = 3; // only search if at least 3 characters were typed 
    public final static long SEARCH_DELAY_MILLIS = (long) 1500; // the time to wait for no text changes in milliseconds 
    private Search search; 
    private AutoCompleteTextView textView; 
    private String[] matches; 
    private String userStartRequest; 
    private Entry[] suggestions; 
    private FragmentListenter sListener; 
    private EntryFunctions ef = new EntryFunctions(); 
    private Runnable delayableSearch; 
    private Runnable delayableAdapterCreation; 
    private Handler delayableSearchHandler;  

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     delayableSearchHandler = new Handler(); 

     delayableSearch = new Runnable() { 
      @Override 
      public void run() { 
       userStartRequest = textView.getText().toString(); 
       sListener.onFragmentFinish(userStartRequest); 
       suggestions = search.getResults(userStartRequest); 
       matches = ef.fillMatches(suggestions); 
      } 
     }; 

     delayableAdapterCreation = new Runnable() { 
      @Override 
      public void run() { 
       ArrayAdapterWithSpaceFilter<String> adapter = 
         new ArrayAdapterWithSpaceFilter<String>(getActivity(), 
           android.R.layout.simple_list_item_1, 
           matches); 
       textView.setAdapter(adapter); 
      } 
     }; 

     // Inflate the layout for this fragment 
     return inflater.inflate(R.layout.fragment_search, container, false); 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 
     textViewHandler(); 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (!(context instanceof FragmentListenter)) throw new AssertionError(); 
     sListener = (FragmentListenter) context; 
    } 

    /** 
    * Interface for communicate to activity 
    */ 
    public interface FragmentListenter { 
     void onFragmentFinish(String userStartRequest); 
    } 


    /** 
    * Handler for the AutoCompleteTextView 
    */ 
    private void textViewHandler() { 
     try { 
      textView = (AutoCompleteTextView) getView().findViewById 
        (R.id.startNaviAutoCompleteTextView); 
      search = new Search(); 
      System.out.println("Created Search object"); 

      textView.addTextChangedListener(new TextWatcher() { 

       @Override 
       public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
        System.out.println("TextWatcher beforeTextChanged"); 
       } 

       @Override 
       public void onTextChanged(CharSequence s, final int start, int before, int count) { 
        delayableSearchHandler.removeCallbacks(delayableSearch);      userStartRequest = textView.getText().toString(); 
        sListener.onFragmentFinish(userStartRequest); 
        if (textView.getText().length() >= 
          SEARCH_CHAR_AMOUNT) { 
         new Thread(delayableSearch).start(); 
         delayableSearchHandler.postDelayed 
          (delayableAdapterCreation, SEARCH_DELAY_MILLIS); 
        } 
       } 

       @Override 
       public void afterTextChanged(Editable s) { 
       } 
      }); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

、計算がすでに新しい文字がAutoCompleteTextViewに入力されるたびに開始され、最終的に古い検索がキャンセルまたは検索が1.5秒後に開始されているかどうか、私には関係ありません。

検索語句に結果が得られず、結果リストに問題がある場合、上記のコードはクラッシュします。ときには、いくつかのキーストローク前に入力されたものが表示されることがあります(abcdをゆっくりと検索すると、abcの検索結果が表示されます)。 delayableSearchHandler.removeCallbacks(delayableSearch)がこれを防止する必要があるにしても、textViewHandlerまたはonTextChangedメソッドを複数回呼び出すと、私の推測は競合状態または何らかの問題になります。

ワーカースレッドとUIスレッドの間のやりとりがどのようになっているのか、誰でも説明できるので、検索で結果が得られることが保証されていますか?事前に

おかげで、

ジョー

答えて

0

どれ長時間実行操作(ネットワーク呼び出し、データベース検索が...)UIをブロックするため、実行に時間がかかることがあります。アイスクリームサンドイッチの前に、この種の行動はアンドロイドランタイムによって許容されました。

This article良いかもしれませんが、私は非常に残念です

+0

を読んで、私は質問にその音のmisunderstandableを作りました。コードの現在の状態はクラッシュしません(以前の試行で多く発生した)。これはただちに検索結果を表示しませんが、遅延時間の計算を実行してから別の文字を追加したり削除したりすると表示されます。 UIとワーカースレッド間の通信と呼び出しが完了すると、それは自己修正でなければならないので、正確なエラーは無関係であると私は思った。 –

+0

私は私が従うとは思わない。あなたのコードは望ましくない結果をもたらしますか?特定の状況下でクラッシュするのですか? –

+0

希望の結果は、1.5秒後(または検索自体に時間がかかる場合はそれ以上)、可能性のある一致のリストがUIに表示されます。このコードでは、リストはランダムに表示されるように感じます。ときには、いくつかのキーストローク前に入力されたものが表示されることがあります(abcdをゆっくりと検索すると、abcの検索結果が表示されます)。検索バーの最初の実装では、追加されたすべての文字の後に計算を行い、UIをフリーズし、終了時に結果を表示してから、ユーザーが別の文字を入力させるようにしました。これは遅すぎた。 –

関連する問題