Android Filter類--線程間的通信

Filter與AsyncQueryHander實現基本類似,它包含兩個Hander:RequestHandler和 ResultHandler,以及一個HandlerThread:名爲Filter的線程。RequestHandler與Filter線程綁定,過濾請求都是通過 RequestHandler發送給Filter線程。當過濾產生後,通過mResultHandler將數據push給UI顯示。

首先看下Filter的構造方法

public Filter() {
        mResultHandler = new ResultsHandler();
    }

private class ResultsHandler extends Handler {
        /**
         * <p>Messages received from the request handler are processed in the
         * UI thread. The processing involves calling
         * {@link Filter#publishResults(CharSequence,
         * android.widget.Filter.FilterResults)}
         * to post the results back in the UI and then notifying the listener,
         * if any.</p> 
         *
         * @param msg the filtering results
         */
        @Override
        public void handleMessage(Message msg) {
            RequestArguments args = (RequestArguments) msg.obj;

//push 給UI顯示
            publishResults(args.constraint, args.results);
            if (args.listener != null) {
                int count = args.results != null ? args.results.count : -1;
                args.listener.onFilterComplete(count);
            }
        }
    }

上一篇文章中說到搜索的方法

adapter.getFilter.filter(*******),實際上調用的就是Filter的filter方法。如下

private static final String THREAD_NAME = "Filter";

public final void filter(CharSequence constraint, FilterListener listener) {
        synchronized (mLock) {
            if (mThreadHandler == null) {
                HandlerThread thread = new HandlerThread(
                        THREAD_NAME, android.os.Process.THREAD_PRIORITY_BACKGROUND);
                thread.start();
                mThreadHandler = new RequestHandler(thread.getLooper());
            }

            final long delay = (mDelayer == null) ? 0 : mDelayer.getPostingDelay(constraint);
            Message message = mThreadHandler.obtainMessage(FILTER_TOKEN);
    
            RequestArguments args = new RequestArguments();
            // make sure we use an immutable copy of the constraint, so that
            // it doesn't change while the filter operation is in progress
            args.constraint = constraint != null ? constraint.toString() : null;
            args.listener = listener;
            message.obj = args;
    
            mThreadHandler.removeMessages(FILTER_TOKEN);
            mThreadHandler.removeMessages(FINISH_TOKEN);
            mThreadHandler.sendMessageDelayed(message, delay);
        }
    }

首先開啓了一個名字爲Filter的HandlerThread。我們看下HandlerThread

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    public int getThreadId() {
        return mTid;
    }
}

該線程中的run方法中什麼都沒有做,只是提供給我們一個該線程的Looper,就是說該線程是有消息循環的線程,既然有消息循環,那麼就應該有自己的Handler來處理消息。得到該線程的handler

mThreadHandler = new RequestHandler(thread.getLooper());

看下RequestHandler

private class RequestHandler extends Handler {
        public RequestHandler(Looper looper) {
            super(looper);
        }
        public void handleMessage(Message msg) {
            int what = msg.what;
            Message message;
            switch (what) {
                case FILTER_TOKEN:
                    RequestArguments args = (RequestArguments) msg.obj;
                    try {
                        args.results = performFiltering(args.constraint);
                    } catch (Exception e) {
                        args.results = new FilterResults();
                        Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
                    } finally {
                        message = mResultHandler.obtainMessage(what);
                        message.obj = args;
                        message.sendToTarget();
                    }
                    synchronized (mLock) {
                        if (mThreadHandler != null) {
                            Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN);
                            mThreadHandler.sendMessageDelayed(finishMessage, 3000);
                        }
                    }
                    break;
                case FINISH_TOKEN:
                    synchronized (mLock) {
                        if (mThreadHandler != null) {
                            mThreadHandler.getLooper().quit();
                            mThreadHandler = null;
                        }
                    }
                    break;
            }
        }
    }

根據構造方法中的looper參數將RequestHandler和名爲Filter的HandlerThread綁定,這樣在其他線程(主線程或者其他子線程)就可以通過該handler給名爲Filter的HandlerThread發消息,處理消息的實際操作在handler中處理。回頭看filter方法中就往RequestHandler發送了一個消息FILTER_TOKEN。RequestHandler的handleMessage中調用performFiltering來進行查詢,查詢得到結果後給主線程發送消息更新UI。並且給自己發送一個FINISH_TOKEN的消息,結束HandlerThread線程。

至此Filter類就分析完了。其中比較有實用價值的就是線程間的通信,在寫其他應用中可以借鑑這種方式

發佈了60 篇原創文章 · 獲贊 3 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章