Problem
Almost all of the apps now have a search function, generally we listen to the EditText control, the value changes to request the search interface. Such as:
Etkey.addtextchangedlistener (NewTextwatcher () {@Override Public void beforetextchanged(Charsequence S,intStartintCountintAfter) {}@Override Public void ontextchanged(Charsequence S,intStartintBefore,intCount) {}@Override Public void aftertextchanged(Editable s) {String key = Etkey.gettext (). toString (). Trim ();if(Key.length () >0) {search (key);//Request Search interface, after successful display the results to the interface.} }});
There are two problems with this:
- Can result in a lot of meaningless requests, consuming user traffic (because the value of the control will go to the network immediately after every change, and only the last keyword entered is useful)
- The result of the final search may not be what the user wants. For example, when a user starts typing the keyword ' AB ' This time there are two requests, a request is a keyword, and a request is the AB keyword. The surface is ' A ' request sent out first, ' AB ' request sent out. If the after-issued ' AB ' request returns first, the ' A ' request returns, then the result of the ' a ' request will overwrite the result of the ' AB ' request. resulting in incorrect search results.
Solve the problem
This problem can be solved by using the powerful Rxjava debounce operator.
subscription = Rxtextview. Textchanges(Etkey). Debounce( -, Timeunit. MILLISECONDS, Androidschedulers. Mainthread()). Subscribeon(androidschedulers. Mainthread())//for Etkey[edittext] The monitoring operation needs to be in the main thread operation//To filter the user input keywords. Filter(New Func1<charsequence, boolean> () {@Override public BooleanPager(Charsequence charsequence) {Log. D("RxJava","Filter is main thread:"+ (Looper. Getmainlooper() = = Looper. Mylooper()));Return charsequence. toString(). Trim(). Length() >0;} }). FlatMap(New Func1<charsequence, observable<list<string>>> () {@Override P Ublic observable<list<string>>Pager(Charsequence charsequence) {Log. D("RxJava", Getmaintext ("FlatMap"));Return SEARCHAPI. Search(charsequence. toString());} }). Subscribeon(schedulers. IO()). Observeon(androidschedulers. Mainthread()). Subscribe(New action1<list<string>> () {@Override public voidPager(List<string> strings) {tvcontent. SetText("Search result:\n\n");Tvcontent. Append(Strings. toString());}}, new Action1<throwable> () {@Override public voidPager(Throwable throwable) {Throwable. Printstacktrace();Tvcontent. Append("Error:"+ Throwable. GetMessage());} });
The main logic of the above code:
- Use the debounce operator setting: Only 400 milliseconds after the user enters the keyword will the data be emitted [the straightforward point is 400 milliseconds before the logic that goes behind];
- Use the filter operator to filter the keywords that are entered by the user: only the input keyword is not empty, the logic behind it will be gone;
- Using the FLATMAP operator: Use the final keyword to request a search interface
At this point, avoid edittext every time a change is requested.
However, there is a problem, the above-mentioned causes the search results of the confusion, the above code is still not resolved, such as stop input 400 milliseconds, then will certainly start to request the search interface, but the user will enter a new keyword, this time the last request has not returned, The new request goes to the search interface. This time it is possible that the last request is returned, and the first request is returned, resulting in the result of the first search.
How to solve this problem: You can use the SWITCHMAP operator to solve.
See how the SWITCHMAP operator is interpreted by the official website:
Returnsa NewObservable byApplyinga function that's supply to each item emitted by the source Observable that returns an Observable, and ThenEmitting the ItemsEmitted by theMost recently emitted ofThese observables.
The SWITCHMAP operator is almost the same as the FLATMAP operator, except that the SWITCHMAP operator only emits the nearest observables of [emit].
That is, when the first search request is made after 400 milliseconds, the user searches again, making a second request, regardless, the switchmap operator only launches the second requested observable. So, on the basis of the above code to change the Flatmap to Switchmap on it.
Functional and practical, really more and more like Rxjava.
Reprint: http://blog.csdn.net/johnny901114/article/details/51555203
RxJava using the debounce operator to optimize the app search function