Red Dot Counter Implementation in a Mobile App
The article explains how to implement a red‑dot badge system in the “玩心部落” mobile app using a tree‑structured RedPoint hierarchy combined with the Observer pattern, where each node tracks its count, notifies UI observers, propagates updates to parent nodes, and is managed centrally by a HeadRedPoint singleton for easy extension.
In many apps, a red dot badge is used to indicate unread counts. This article describes the design and implementation of a red‑dot counting feature for the “玩心部落” mobile application.
The solution is based on a tree data structure (the “red‑point tree”) combined with the Observer pattern. Each node in the tree represents a red‑dot and knows its parent node. Two refresh mechanisms are required: refreshing the UI component associated with the node, and propagating updates to the parent node.
The red‑point tree is anchored by a head node (root) that maintains a Map<String, RedPoint> mapping each node’s unique key to its RedPoint instance.
Key constants defining the identifiers for each node are declared in the IRedPointKey interface:
/**
* 节点Key常量
*/
public interface IRedPointKey {
String KEY_UNKNOWN = "key_unknown"; // 未知节点
String KEY_ROOT = "key_root"; // 根节点,即桌面图标节点
String KEY_MINE_MAIN = "key_mine_main"; // 我的模块
String KEY_MINE_FANS = "key_mine_fans"; // 我的‑粉丝
String KEY_MINE_FOLLOW = "key_mine_follow"; // 我的‑关注
String KEY_MESSAGE_MAIN = "key_message_main"; // 消息模块
String KEY_MESSAGE_GAME = "key_message_game"; // 消息‑游戏子模块
String KEY_MESSAGE_SUB_MESSAGE_MAIN = "key_message_sub_message_main"; // 消息‑子模块
String KEY_MESSAGE_SUB_MESSAGE_REPLY = "key_message_sub_message_reply"; // 回复我的
String KEY_MESSAGE_SUB_MESSAGE_MENTION = "key_message_sub_message_mention"; // @我的
String KEY_MESSAGE_SUB_MESSAGE_PRAISE = "key_message_sub_message_praise"; // 收到的赞
String KEY_MESSAGE_SUB_MESSAGE_TRIBAL_MANAGER = "key_message_sub_message_tribal_manager"; // 部落管家
String KEY_MESSAGE_SUB_MESSAGE_SYSTEM = "key_message_sub_message_system"; // 系统消息
}The RedPoint class represents a leaf or intermediate node. It extends Observable and holds the parent key, current count, and an Observer that updates the UI.
/**
* 红点节点。子节点是被观察者,当子节点的数据变化时,通知刷新UI,并更新父节点的数据。
*/
public class RedPoint extends Observable {
private String parentKey; // 父节点Key
private int count = 0; // 当前红点数
private Observer viewObserver; // UI观察者
... // constructors, getters, setters
public void setCount(int count) {
this.count = count;
notifyChange();
}
private void notifyChange() {
HeadRedPoint.getInstance().updateCount(parentKey);
setChanged();
notifyObservers(this.count);
}
}The HeadRedPoint singleton maintains the map of all nodes and provides methods to initialize the tree, retrieve nodes, and update parent counts.
public class HeadRedPoint {
private static HeadRedPoint headRedPoint;
private Map
redPointMap = new HashMap<>();
private HeadRedPoint() { initRedPoint(); }
public static HeadRedPoint getInstance() { ... }
private void initRedPoint() {
redPointMap.put(IRedPointKey.KEY_ROOT, new RedPoint());
redPointMap.put(IRedPointKey.KEY_MINE_MAIN, new RedPoint(IRedPointKey.KEY_ROOT));
redPointMap.put(IRedPointKey.KEY_MINE_FANS, new RedPoint(IRedPointKey.KEY_MINE_MAIN));
// ... other nodes ...
}
protected void updateCount(String parentKey) {
int totalCount = 0;
for (RedPoint rp : redPointMap.values()) {
if (parentKey.equals(rp.getParentKey())) {
totalCount += rp.getCount();
}
}
redPointMap.get(parentKey).setCount(totalCount);
}
// additional utility methods ...
}Usage examples:
To add an observer that refreshes a UI component when the “回复我的” (reply to me) red dot changes:
// Add observer to the reply‑to‑me node
HeadRedPoint.getInstance().getRedPoint(IRedPointKey.KEY_MESSAGE_SUB_MESSAGE_REPLY)
.setViewObserver(new Observer() {
@Override public void update(Observable o, Object arg) {
// Refresh UI with new count (arg)
}
});To modify the count of that node:
HeadRedPoint.getInstance().getRedPoint(IRedPointKey.KEY_MESSAGE_SUB_MESSAGE_REPLY).setCount(1); // set to 1
HeadRedPoint.getInstance().getRedPoint(IRedPointKey.KEY_MESSAGE_SUB_MESSAGE_REPLY).addCount(1); // increment
HeadRedPoint.getInstance().getRedPoint(IRedPointKey.KEY_MESSAGE_SUB_MESSAGE_REPLY).minusCount(1); // decrement
HeadRedPoint.getInstance().getRedPoint(IRedPointKey.KEY_MESSAGE_SUB_MESSAGE_REPLY).clearCount(); // resetThe article also notes that extending or modifying the red‑dot system only requires updating the key constants and the initRedPoint() method to reflect new relationships.
37 Interactive Technology Team
37 Interactive Technology Center
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.