Filter.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.HandlerThread;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>A filter constrains data with a filtering pattern.</p>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Filters are usually created by {@link android.widget.Filterable}
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * classes.</p>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Filtering operations performed by calling {@link #filter(CharSequence)} or
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #filter(CharSequence, android.widget.Filter.FilterListener)} are
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * performed asynchronously. When these methods are called, a filtering request
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is posted in a request queue and processed later. Any call to one of these
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * methods will cancel any previous non-executed filtering request.</p>
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.Filterable
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class Filter {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOG_TAG = "Filter";
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String THREAD_NAME = "Filter";
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int FILTER_TOKEN = 0xD0D0F00D;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int FINISH_TOKEN = 0xDEADBEEF;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mThreadHandler;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mResultHandler;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Creates a new asynchronous filter.</p>
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Filter() {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResultHandler = new ResultsHandler();
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Starts an asynchronous filtering operation. Calling this method
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cancels all previous non-executed filtering requests and posts a new
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * filtering request that will be executed later.</p>
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param constraint the constraint used to filter the data
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #filter(CharSequence, android.widget.Filter.FilterListener)
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void filter(CharSequence constraint) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter(constraint, null);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Starts an asynchronous filtering operation. Calling this method
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cancels all previous non-executed filtering requests and posts a new
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * filtering request that will be executed later.</p>
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Upon completion, the listener is notified.</p>
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param constraint the constraint used to filter the data
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener a listener notified upon completion of the operation
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #filter(CharSequence)
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #performFiltering(CharSequence)
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #publishResults(CharSequence, android.widget.Filter.FilterResults)
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void filter(CharSequence constraint, FilterListener listener) {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mThreadHandler == null) {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                HandlerThread thread = new HandlerThread(THREAD_NAME);
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                thread.start();
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mThreadHandler = new RequestHandler(thread.getLooper());
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message message = mThreadHandler.obtainMessage(FILTER_TOKEN);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            RequestArguments args = new RequestArguments();
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // make sure we use an immutable copy of the constraint, so that
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // it doesn't change while the filter operation is in progress
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args.constraint = constraint != null ? constraint.toString() : null;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            args.listener = listener;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            message.obj = args;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mThreadHandler.removeMessages(FILTER_TOKEN);
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mThreadHandler.removeMessages(FINISH_TOKEN);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mThreadHandler.sendMessage(message);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Invoked in a worker thread to filter the data according to the
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constraint. Subclasses must implement this method to perform the
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * filtering operation. Results computed by the filtering operation
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * must be returned as a {@link android.widget.Filter.FilterResults} that
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will then be published in the UI thread through
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #publishResults(CharSequence,
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * android.widget.Filter.FilterResults)}.</p>
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p><strong>Contract:</strong> When the constraint is null, the original
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data must be restored.</p>
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param constraint the constraint used to filter the data
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the results of the filtering operation
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #filter(CharSequence, android.widget.Filter.FilterListener)
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #publishResults(CharSequence, android.widget.Filter.FilterResults)
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see android.widget.Filter.FilterResults
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected abstract FilterResults performFiltering(CharSequence constraint);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Invoked in the UI thread to publish the filtering results in the
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * user interface. Subclasses must implement this method to display the
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * results computed in {@link #performFiltering}.</p>
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param constraint the constraint used to filter the data
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param results the results of the filtering operation
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #filter(CharSequence, android.widget.Filter.FilterListener)
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #performFiltering(CharSequence)
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see android.widget.Filter.FilterResults
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected abstract void publishResults(CharSequence constraint,
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FilterResults results);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Converts a value from the filtered set into a CharSequence. Subclasses
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should override this method to convert their results. The default
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * implementation returns an empty String for null values or the default
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * String representation of the value.</p>
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param resultValue the value to convert to a CharSequence
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a CharSequence representing the value
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence convertResultToString(Object resultValue) {
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return resultValue == null ? "" : resultValue.toString();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Holds the results of a filtering operation. The results are the values
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * computed by the filtering operation and the number of these values.</p>
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected static class FilterResults {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public FilterResults() {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // nothing to see here
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>Contains all the values computed by the filtering operation.</p>
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Object values;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>Contains the number of values computed by the filtering
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * operation.</p>
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int count;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Listener used to receive a notification upon completion of a filtering
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * operation.</p>
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static interface FilterListener {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>Notifies the end of a filtering operation.</p>
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param count the number of values computed by the filter
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onFilterComplete(int count);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Worker thread handler. When a new filtering request is posted from
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.widget.Filter#filter(CharSequence, android.widget.Filter.FilterListener)},
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it is sent to this handler.</p>
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class RequestHandler extends Handler {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public RequestHandler(Looper looper) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(looper);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>Handles filtering requests by calling
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link Filter#performFiltering} and then sending a message
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * with the results to the results handler.</p>
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param msg the filtering request
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int what = msg.what;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Message message;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (what) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case FILTER_TOKEN:
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    RequestArguments args = (RequestArguments) msg.obj;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        args.results = performFiltering(args.constraint);
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (Exception e) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        args.results = new FilterResults();
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } finally {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        message = mResultHandler.obtainMessage(what);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        message.obj = args;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        message.sendToTarget();
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (mThreadHandler != null) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThreadHandler.sendMessageDelayed(finishMessage, 3000);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case FINISH_TOKEN:
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (mThreadHandler != null) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThreadHandler.getLooper().quit();
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mThreadHandler = null;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Handles the results of a filtering operation. The results are
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * handled in the UI thread.</p>
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class ResultsHandler extends Handler {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>Messages received from the request handler are processed in the
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * UI thread. The processing involves calling
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link Filter#publishResults(CharSequence,
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * android.widget.Filter.FilterResults)}
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to post the results back in the UI and then notifying the listener,
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * if any.</p>
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param msg the filtering results
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            RequestArguments args = (RequestArguments) msg.obj;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            publishResults(args.constraint, args.results);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (args.listener != null) {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int count = args.results != null ? args.results.count : -1;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                args.listener.onFilterComplete(count);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Holds the arguments of a filtering request as well as the results
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the request.</p>
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class RequestArguments {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>The constraint used to filter the data.</p>
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CharSequence constraint;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>The listener to notify upon completion. Can be null.</p>
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FilterListener listener;
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * <p>The results of the filtering operation.</p>
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FilterResults results;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
291