WQthrottle is a message stabilization framework that triggers a callback to a result only once over a certain amount of time.

use

To use it, check out github’s README.

Development purposes

The framework was developed to address the following pain points:

  • Redundant operation requests
  • Multi-page messaging

Pain point 1 (Redundant operation requests)

This pain point comes up a lot in our business. Here are two more common business operations:

give a like

When we design “like”, every “like” operation will request the server to inform the server whether it is “like” or “cancel”. If users click “like” frequently at this time, it will lead to too many network requests, resulting in unnecessary waste. In terms of design, the “like” function is nothing more than two states, “like” or “not like”. We can wait for the user to stop operation and then request the server.

search

Real-time search to display the search content is also a common function in our daily business. We register TextWatcher monitor for EditText, get the user’s input content in real time in onTextChanged, and then request the network. It seems to be an operation without any problems, but it is due to the input habits of different users. Some people type very slowly, typing a few phrases and onTextChanged asks the server to display the results as soon as they receive the message, while others type very fast and hit the EditText with each phrase, which results in frequent network requests and, worse, frequent page rendering. 100 requests will result in 100 page renders.

Pain point 2 (Multi-page messaging)

In the early days of Android development, the message delivery on a page was usually Intent, sending back the result via setResult to the previous page, which was very painful until EventBus, a very popular decoupled framework, came along. You can send and receive messages anywhere, but for me, the disadvantages are quite numerous:

  • Subcribe is too random, which leads to the chaos of subsequent projects and is difficult to maintain
  • The internal implementation of Eventbus is reflection, and performance needs to be considered
  • Every time I post a message, I wonder if this bean will affect the reception of other messages. Instead, I will create a bean class

The principle of analyzing

The implementation principle is very simple, just one core thing —— Handler

Initialize the

Instantiate the singleton used by the initialization operation, which by default constructs a handler handler class:

 handler = HandlerFactory.create(HandlerType.MAIN_THREAD, callBacks);
Copy the code

HandlerType is an enumeration class that tells the receiver whether it is on the main or child thread, see the HandlerFactory class.

registered

Registering is very simple, just registering a CallBack interface, and waiting for a POST message, the registered CallBack will be called again and again

private List<CallBack> callBacks = new ArrayList<>();
public void register(CallBack callBack) {
        callBacks.add(callBack);
}
Copy the code

Send a message

The core of the entire framework for sending messages:

WQThrottle.getInstance().delay(int tag, long timeMillis, Object params);
Copy the code

Let’s look at what Delay does:

   public void delay(int tag, long timeMillis, Object params) {
        handler.removeMessages(tag);
        Message msg = handler.obtainMessage();
        msg.obj = params;
        msg.what = tag;
        handler.sendMessageDelayed(msg, timeMillis);
   }
Copy the code

Again, very simple, is within the delay time, remove the previously triggered message, and then send the message again, until the user does not trigger, when the delay time, the message will be sent.

The message received

To receive the message, look at the callback section of the code:

new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg); sendMessages(msg, callBacks); }};private static void sendMessages(Message msg, List<WQThrottle.CallBack> callBacks) {
        for (int i = 0, len = callBacks.size(); i < len; i++) { callBacks.get(i).throttleResult(msg.what, msg.obj); }}Copy the code

The sent message is received by the Handler, which iterates through all CallBack registered interfaces and posts the message.

 @Override
 public void throttleResult(int tag, Object obj) {
     switch(tag){//do something}
 }
Copy the code

CallBack compares the sent tag to determine what the operation is, and then retrieves the parameter obj.

The end of the

The whole design is very simple, and the message-based framework is implemented only through Handler.

Not much. That’s it