Use tree model to manage App numbers and red dot prompts (with Demo)


Most of the apps we usually come into contact with, when new messages are received, they are usually displayed in the form of numbers or red dots. For example, in WeChat, when a friend sends us a new chat message, there will be a number in the corresponding conversation to indicate the number of unread messages; another example is when someone in WeChat Moments publishes new content At the moment, a red dot will appear at the entrance of Moments, and when someone in Moments likes us or comments on the content we posted, the entrance of Moments will show a number.


However, when we try out some new App products, we always find that they have various problems in digital and red dot display. For example, the red dot can't be removed even if you click it; or, if there are numbers, click in but there is nothing; or, the numbers you click in and see outside are different.


So how did these problems arise?


I guess that the root cause of the problem is that there is no unified abstraction and management of the display logic of numbers and red dots, so that the relationship between various numbers and red dots is intricate and affects the whole body. In this way, in the App maintenance process, if there is a slight change (such as adding a few numbers or red dot type), the probability of a problem is very high.


This article will propose a tree structure model to uniformly manage the hierarchical structure of numbers and red dots, and will give a runable Android version of the Demo program at the end of the article for reference.


If you happen to have an Android phone at hand, you can scan and identify the QR code below to download and install this demo, and take a few minutes to see if it is useful to you. Note: The correct operation procedure in WeChat is to click "Open in browser" in the upper right corner after recognizing the QR code, then you can jump to the download page and finally complete the download (please click on the download page of Baidu Cloud Normal download").


image


Simple digital red dot management


For the convenience of discussion, we first make a simple arrangement of the requirements for the display of numbers and red dots under normal circumstances, and then see what the most intuitive way to achieve such requirements may be.


  • Some new messages are important and need to be displayed as numbers; some new messages are not so important and need to be displayed as red dots. For example, I have received new comments or received new likes, which is more reasonable in numbers; and for some system messages sent to me by the system, I hope it will not interfere with my sight too much. The red dot form of display is more reasonable.

  • Numbers and red dots need to be displayed hierarchically. When a new message arrives, the user can start from the App homepage (the first level page), follow the numbers and red dot prompts, step by step to deeper pages, and finally reach the terminal page where the new message is displayed. For example, in the screenshot of the App below, when a user receives a new comment, a digital prompt will first appear on the second Tab (the "message" Tab), leading the user to the second Tab page, and then on the page A digital prompt will continue to be displayed next to "comments received" to guide users to click into a deeper comment page.


image


  • If a digital prompt of a certain level contains multiple digital prompts on its deeper page, then the number of this level should be the sum of the numbers of the deeper page. For example, the number of messages in the figure above is 5=4+1.

  • If a certain level of numbers (red dots) indicates that there are both numbers and red dots on the pages of a deeper level, then this level will be displayed as numbers first; if the numbers on the deeper level pages are cleared, only The red dot is displayed, then this level will be displayed according to the red dot. For example, in the App screenshot below, there are only system messages on the page, and the system messages are displayed with red dots, so the second Tab also becomes a red dot.


image


I believe the points summarized above are roughly similar to the display logic of most apps. Even if there are some differences, it should not hinder our subsequent discussion.


Ok, now let's consider the implementation based on the specific situation in the App screenshot above. The "message" Tab contains "comments received", "likes received" and "system messages", where comments and likes are numbers, and system messages are red dots.


We individually consider the display logic of the digital red dot on the "message" Tab, and it is not difficult to write a code similar to the following (pseudo code):


image


This code can certainly meet the requirements, but the shortcomings are also obvious. The most important thing is that it requires the display logic on the "message" tab to list all the sub-message types (comments, likes, system messages) contained below, and know whether each type is a number or a red dot. The above only gives the situation of two-level pages. What if there are three-level pages or even more? Then this information must be repeated on all levels of pages.


This will complicate maintenance and modification. Imagine that a new message type is added under "Messages", or a certain type of message is displayed from a digital display to a red dot display, or even a certain type of message is moved from one page stack to another page Stack up. In all these cases, all pages at higher levels are required to be modified accordingly. When an App has more and more message types, reaching dozens of messages, it is conceivable that this kind of modification is very error-prone.


Digital red dot management method based on tree model


The problems mentioned above, we also encountered in the early stage of the development of the Wei Ai App. Later, we re-examined the structure of the red dot and digital display in the App, using a tree structure to look at it, making maintenance easier.


The page of an App is hierarchical, and the access path to the page is essentially a tree structure.


image

As shown in the figure above, node 1 represents the first level page. Below this page contains three deeper (level 2) page entries, corresponding to nodes 2, 3, and 4. One level deeper, you will reach the terminal page, which is represented by a green square node.


The tree model can be expressed as follows:


  • The leaf node (the green square node) represents the terminal page where the message is finally displayed. How the message is displayed on the leaf nodes is determined during product design. For example, it can display the message directly, or display a number first, click in and then display the content of the message (like the comment number prompt in the screenshot of the previous App), or it can pop up to prompt. In short, its display style is solidified in the code of the product business.

  • The middle node (circular orange node) represents the page on the access path from the level 1 page to the message terminal page. The display on the intermediate node is generally a number or a red dot.

  • Each message type is called a Badge Number. It has three attributes:

    • type: Badge Number type.

    • count: count, for each Badge Number, one count for each user.

    • displayMode: The display mode of the current badge number on the parent node. 0 means red dot, 1 means number.

  • Badge Number belongs to different categories according to different business types. The Badge Number types in each category are allocated in the same type range. For example, the 2, 3, and 4 nodes in the tree structure diagram above correspond to three business types, that is, three major categories. Their corresponding type intervals are [A, C], [X, Y], [R, T]. To give another practical example, for example, WeChat Moments is a big business category, and the Badge Number types in it include: someone commented on me (number), someone gave me a thumbs up (number), and friends posted new messages (red dot), Wait.


In order to make the Badge Number in a large category expressed in a type range, when assigning values ​​to the type, we can take a similar approach: Use an int to represent the Badge Number type, and its high 16 bits are used Represents a broad category. For example, if the high 16 bits of the "message" category is 0x2, then the three types of Badge Numbers (types) it contains can be allocated as follows:


  • Comments received: (0x2 «16) + 0x1

  • Likes received: (0x2 «16) + 0x2

  • System message: (0x2 «16) + 0x3


In this way, the “message” category can be expressed by a type interval [(0x2 «16) + 0x1, (0x2« 16) + 0x3].


After having the type interval, let's revisit the intermediate nodes in the tree model. They can all be represented by one or more type intervals. Their display logic (whether they are displayed as numbers, red dots, or hidden) requires the sum of the type intervals of all subtrees. The specific summing process is:


  • First, sum the number types in all the types range, if it is greater than 0, then display the number; otherwise,

  • Sum the red dot types in all the type intervals, if it is greater than 0, display the red dot; otherwise,

  • Hide the numbers and red dots.


Code implementation of tree model


The implementation of the tree model is called Badge Number Tree. This article provides an Android version of the Demo implementation. The source code can be downloaded from GitHub: https://github.com/tielei/BadgeNumberTree  .


Let's analyze the key parts.


The main implementation class of the Android version is BadgeNumberTreeManager, and its key code is as follows (in order not to affect our understanding of the main logic, the non-key code is ignored below and not posted. If you need to view it, please download the source code on GitHub; please click to see the code below Big picture):


image


The points we need to pay attention to in this code include:


  • The four operations for adding, deleting, modifying and checking Badge Number in the previous section-setBadgeNumber, addBadgeNumber, clearBadgeNumber, getBadgeNumber, are relatively simple, and the implementation code is not posted here. In fact, in Demo, it is implemented based on SQLite local storage. What we need to pay attention to is the application scenarios of each operation:

    • setBadgeNumber is used for general new message reminders. It is called when a new message reminder is generated, and the Badge Number is stored locally. The count value in these Badge Numbers is maintained by the server, so the server shall prevail, and each time it is obtained from the server, setBadgeNumber is mobilized to overwrite the local value.

    • addBadgeNumber is used to remind messages of local cumulative count, such as chat messages. The new chat message received by a user is counted locally, so addBadgeNumber is used to accumulate the count.

    • clearBadgeNumber is used to clear the Badge Number of the specified type. Generally speaking, when users finish reading new messages on the message terminal page (tree-shaped leaf nodes), they need to clear the Badge Number.

    • getBadgeNumber, get the value of Badge Number according to the specified type, used to call when the message is displayed on the message terminal page (tree-shaped leaf node).

  • Finally, there is a private getBadgeNumber method, which is different from the previous public overload method. It does not take a specified type of Badge Number, but takes a specified display mode (displayMode) in the type range [typeMin, typeMax] The total number of badge numbers. This method is the basis for implementing the Badge Number display logic on the intermediate node. The implementation code here is also not posted, and its implementation is actually relatively simple. In the Demo, it is implemented based on a sum operation performed by SQLite.

  • The public getTotalBadgeNumberOnParent is a key method, which is used to implement the Badge Number display logic on the intermediate node. The input typeIntervalList parameter is a list of type intervals, corresponding to an intermediate node. Its asynchronous output parameter is a BadgeNumberCountResult object, which can express three display results: number, red dot, and hidden (no display). The implementation of this method is to call another private overload method of it, successively sum the number type and the red dot type on the type interval list (this is the sum of all the subtree type intervals of the intermediate node mentioned earlier) achieve).


The code example for calling getTotalBadgeNumberOnParent is as follows:


image


Some supplementary notes on implementation


  • In the Demo program, the underlying storage of BadgeNumberTreeManager uses SQLite. However, due to the frequent interface calls of BadgeNumberTreeManager, an intermediate first-level memory cache was added to the implementation (see GitHub code for details).

  • After the client obtains the new Badge Number in some way, it saves it locally (through the setBadgeNumber and addBadgeNumber interfaces of BadgeNumberTreeManager). There may be many ways for the client to obtain the Badge Number, such as pushing it to the client via a persistent connection (a persistent connection implemented by the App itself, or a persistent connection from a third-party platform), or pulling it through an HTTP service (this method is applicable For new tips that are not real-time).

  • The display refresh logic of the Badge Number of the intermediate node (that is, calling the getTotalBadgeNumberOnParent interface of BadgeNumberTreeManager) needs to be executed at all necessary times. Take the Android version of the demo given in this article as an example. These timings include: when the page is onResume, when the sub-Tab is switched, and when a new Badge Number is obtained. The timing of execution of the display refresh logic is inaccurate or missing, which is also a common cause of problems with the digital red dot display of the App.

  • There are two common situations for clearing the Badge Number of the intermediate node: (1) It is cleared after all the child nodes are cleared; (2) It is cleared as long as it is clicked, regardless of whether the child nodes are cleared. The Demo given in this article is implemented in the former case. If you want to achieve the latter case, you need to record a separate mark for each intermediate node, but this change is not big.

  • Although the code examples given in this article are based on Android Java, the tree model given in this article can also be used for non-Android Java versions of App implementation.


Guess you like

Origin blog.51cto.com/15049790/2562673