Android Source Angle Full Understanding Filter

Source: Internet
Author: User

Write a ListView Easy, write a adapter easy, your own new thread filter data is also easy, but how to maximize the efficiency of filtering, have to mention the android comes with the filter class.

Some students must ask, filter data to write a completely no problem, why use the filter class with Android? I used to write thread filtering myself, but recently I encountered a low-distribution machine in my project, Dual-core 0.8GCPU, filtering effect is really bad, optimization, using the Android internal filter to try the effect, the results are really better than their own writing, so seriously study the next source, from beginning to end, forget the following:

 Private StaticFinal String Log_tag ="Filter"; Private StaticFinal String Thread_name ="Filter"; Private StaticFinalintFilter_token =0xd0d0f00d; Private StaticFinalintFinish_token =0xDEADBEEF; PrivateHandler Mthreadhandler; PrivateHandler Mresulthandler; PrivateDelayer Mdelayer; PrivateFinal Object MLock =NewObject ();
View Code

In fact, there are only 8 global variables, and half of them are constants: Two handler, one delayer, one object lock. Google development Daniel with these variables and a few local variables to make a very good expansion of the filter, has to be admired.

First look at the construction method:

     Public Filter () {        new  Resultshandler ();    }
View Code

One of the two small strong construction methods--resultshandler has been created, as the name implies to deal with the results of filtering operations. Let's look at the definition of this class:

  Private classResultshandler extends Handler {/** * <p>messages received from the request handler is processed in the * UI thread. The processing involves calling * {@link filter#publishresults (charsequence, * android.widget.Filter.Filte          Rresults)} * To post the results back on the UI and then notifying the listener, * if any.</p> * * @param msg The filtering results*/@Override Public voidhandlemessage (Message msg) {requestarguments args=(requestarguments) msg.obj;            Publishresults (Args.constraint, args.results); if(Args.listener! =NULL) {                intCount = args.results! =NULL? Args.results.count:-1;            Args.listener.onFilterComplete (count); }        }    }    /** * <p>holds The arguments of a filtering request as well as the results * of the request.</p> */    Private Static classrequestarguments {/** * <p>the constraint used to filter the data.</p>*/charsequence constraint; /** * <p>the Listener to notify upon completion. Can be null.</p>*/Filterlistener Listener; /** * <p>the results of the filtering operation.</p>*/filterresults results; }    /** * @hide*/     Public InterfaceDelayer {/** * @param constraint the constraint passed to {@link filter#filter (charsequence)} * @return The delay That should is used for * {@link handler#sendmessagedelayed (android.os.Message, Long)}*/        Longgetpostingdelay (charsequence constraint); }
View Code

Note that the main operation is to call the abstract Publishresults () method for the UI thread to update the screen after Resultshandler receives the message.

Next, look directly at the main filter method:

     PublicFinalvoidfilter (charsequence constraint, Filterlistener listener) {synchronized (mLock) {if(Mthreadhandler = =NULL) {Handlerthread thread=NewHandlerthread (Thread_name, Android.os.Process.THREAD_PRIORITY_BACKGROUND);                Thread.Start (); Mthreadhandler=NewRequestHandler (Thread.getlooper ()); } FinalLongDelay = (Mdelayer = =NULL) ?0: Mdelayer.getpostingdelay (constraint); Message Message=mthreadhandler.obtainmessage (Filter_token); Requestarguments args=Newrequestarguments (); //Make sure we use a immutable copy of the constraint, so//it doesn ' t change while the filter operation are in progressArgs.constraint = constraint! =NULL? Constraint.tostring ():NULL; Args.listener=Listener; Message.obj=args;            Mthreadhandler.removemessages (Filter_token);            Mthreadhandler.removemessages (Finish_token);        mthreadhandler.sendmessagedelayed (message, delay); }    }
View Code

Official documentation This method will open an asynchronous filter operation, call this method will cancel the previously not performed filtering operation, let us analyze how they do it.

First, the entire method is in sync block synchronized (mLock) {}, the intention is straightforward: other methods I don't care, queue up, eat fruit, you one, I one, you next filter method call must wait for me this time the filter method call ends. Then, create a handlerthread, this handlerthread everyone can view the source code, is actually to bring a handler vitamin--looper, with Looper, Can initialize our filter two small strong bis (Processing request operation): Mthreadhandler = new RequestHandler (Thread.getlooper ()), and then get a message message = Mthreadhandler.obtainmessage (Filter_token); Finally remove the previous tags with filter_token and finish_token (because the subsequent operations are time-consuming, you don't know exactly what state to perform) , so that after this method is executed, all operations that perform the filtering must have only one message in the passed

The beauty of this approach is that the method itself is simple and almost time-consuming, and even if you constantly call the filter () method, the program always guarantees that only one message is doing the filtering operation.

Next look at this RequestHandler class;

 Private classRequestHandler extends Handler { PublicRequestHandler (Looper Looper) {super (Looper); }                /** * <p>handles filtering requests by calling * {@link filter#performfiltering} and then sending A message * with the results to the results handler.</p> * * @param msg the filtering reques T*/         Public voidhandlemessage (Message msg) {intwhat =Msg.what;            Message message; Switch(what) { Casefilter_token:requestarguments args=(requestarguments) msg.obj; Try{args.results=performfiltering (Args.constraint); } Catch(Exception e) {args.results=Newfilterresults (); 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, the); }                    }                     Break;  Casefinish_token:synchronized (mLock) {if(Mthreadhandler! =NULL) {Mthreadhandler.getlooper (). Quit (); Mthreadhandler=NULL; }                    }                     Break; }        }    }
View Code

In fact, in addition to the filter method, the main high-end logic is here, imagine a scene, if I call the filter five times, the 1th of the 5 msg has been removed, but it is called by the performfiltering () time-consuming task is still in progress, 2, 3, 4 sure the queue process was killed by the 5th msg, and then the 1th MSG filter operation completed, send a message to Resultshandler update UI, and then give RequestHandler a three-second delay message,

Then execute the MSG5, then call again FILTER,MSG1 and Msg5 is killed, and then the same is done by the MSG5 call Performfiltering () and then execute MSG6, then MSG5 and Msg6 eventually generate a delay message, MSG5 generated by the delay message Mthreadhandler destroyed, MSG6 generated delay message to the time, do not do any action.

We saw a synchronized (MLock) {} in the filter () earlier, and in this handler there are two synchronous code blocks, and the synchronization code block in case Finish_token guarantees that If you have just created Mthreadhandler (which is the UI thread's action) in filter, you will immediately remove all previous delay messages, thus not destroying mthreadhandler here to cause null pointer exceptions. Case Filter_token in the role of the synchronization code block, there is still no way to figure out what is the use, because cases Filter_token and Finish_token is the queue execution, there is no contention lock, So there will be no space between the threads caused by the null pointer, there is a master can see the role also hope to enlighten.

Well, to sum up, in fact, the author is the use of the Looper in the MessageQueue queue of features, there are two objects synchronous lock magic, to ensure that the UI thread and Handlerthread do not conflict, While the filtering process of some redundant MSG was created by the new msg to kill, a thread in order, big Daniel!

PS, if you do not understand the working mechanism of handler and Looper, you can first look at this post:

Http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html

It's so hard to write a post!

Android Source Angle Full Understanding Filter

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.