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類就分析完了。其中比較有實用價值的就是線程間的通信,在寫其他應用中可以借鑑這種方式