AutoCompleteTextView
のテキストを受け取るAndroidアプリで検索機能を実装しようとしていますが、最後の1.5秒間に変更が加えられていないのを待って検索を示します結果。このため私はTextWatcher
クラスを使用します。UIフリーズのない計算が完了するまで待つ
しかし、この動作を実装しようとする私の試みは、UIスレッド自体(runOnUIThread
経由)または前に呼び出されたLooper.prepare()
のスレッドでのみ許可されているいくつかの関数で問題になりました。
追加の文字を入力したり削除したり、検索結果を表示したり、開始アクティビティにリロードしたりすると、アプリがランダムにクラッシュします。
以下は、私がHandler
を使用している私の最近の試みの単純なレクリエーションです。
search.getResults
は長い計算とmatches
はArrayAdapterWithSpaceFilter
を作成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スレッドの間のやりとりがどのようになっているのか、誰でも説明できるので、検索で結果が得られることが保証されていますか?事前に
おかげで、
ジョー
を読んで、私は質問にその音のmisunderstandableを作りました。コードの現在の状態はクラッシュしません(以前の試行で多く発生した)。これはただちに検索結果を表示しませんが、遅延時間の計算を実行してから別の文字を追加したり削除したりすると表示されます。 UIとワーカースレッド間の通信と呼び出しが完了すると、それは自己修正でなければならないので、正確なエラーは無関係であると私は思った。 –
私は私が従うとは思わない。あなたのコードは望ましくない結果をもたらしますか?特定の状況下でクラッシュするのですか? –
希望の結果は、1.5秒後(または検索自体に時間がかかる場合はそれ以上)、可能性のある一致のリストがUIに表示されます。このコードでは、リストはランダムに表示されるように感じます。ときには、いくつかのキーストローク前に入力されたものが表示されることがあります(abcdをゆっくりと検索すると、abcの検索結果が表示されます)。検索バーの最初の実装では、追加されたすべての文字の後に計算を行い、UIをフリーズし、終了時に結果を表示してから、ユーザーが別の文字を入力させるようにしました。これは遅すぎた。 –