Notification Channel 的分组策略,太多渠道怎么办
「Notification Channel 的分组策略,太多渠道怎么办」
做内容聚合类应用的工程师大概率都遇到过这个窘境:产品运营要求每个栏目单独开关通知,技术侧为了把控制权交给用户,在 Android O 之后为每个栏目都建了独立的 Notification Channel。三五年迭代下来,渠道数量从最初的三五个膨胀到五六十个,用户打开系统设置里的通知管理页,需要滑十几屏才能看完。更麻烦的是,有些渠道早就不在业务里了,ID 还残留在系统数据库里,调用 getNotificationChannels() 时返回的列表长得吓人。
Notification Channel 的设计初衷是把通知的细粒度控制权交还给用户,但 API 26 只给了创建和分组的工具,没给"大规模渠道运营"的最佳实践。很多应用把 Channel 当成业务标签来用,结果渠道列表变成了另一份维护负担。这篇文章想聊的,就是怎么在工程层面控制渠道数量,以及 NotificationChannelGroup 到底能救多少场。
渠道膨胀:工具类与内容型产品的不同灾难
最早接触 Notification Channel 时,大多数工具类 App 的分法都很直觉:下载一个渠道、上传一个渠道、安全告警一个渠道、社媒推送一个渠道。这种按功能模块划分的模型,渠道数量通常能控制在十个以内,问题不大。灾难往往发生在内容型产品里——新闻客户端要给体育、科技、娱乐各建一个渠道,体育底下还要拆出 NBA、英超、中超;社区产品要给关注、点赞、私信、系统公告分别建渠道,然后运营说不同话题圈也要独立开关。
每新增一个内容分类,代码里就多了几行:
NotificationChannel channel = new NotificationChannel(
"topic_" + categoryId,
categoryName,
NotificationManager.IMPORTANCE_DEFAULT
);
notificationManager.createNotificationChannel(channel);问题是,createNotificationChannel() 并不是一个纯内存操作。它通过 Binder 跨进程写到 NotificationManagerService,在系统数据库里持久化一条记录。Channel 的 Name、Description、Importance、Sound、Vibration 等字段都会被序列化存储。当这个调用发生在 Application.onCreate() 里,且数量达到几十次时,冷启动 trace 上能明显看到 android.app.INotificationManager$Stub$Proxy.createNotificationChannels 的耗时。低端机上批量创建三十个渠道,主线程被卡住一百毫秒以上并不罕见。
Google 在文档里并没有给一个明确的渠道数量上限,但 Settings 的 UI 是有物理极限的。超过五十个渠道后,用户几乎不可能在系统设置里完成精细管理。更隐蔽的坑在于,NotificationManager.getNotificationChannels() 返回的列表会包含那些被删除的渠道(状态为 deleted),这会让"看看我现在有多少有效渠道"这件事都变得不直观。
NotificationChannelGroup 的 API 边界与假象
Android 8.0 引入 NotificationChannelGroup 时,很多开发者以为它像文件夹一样,可以批量控制组内渠道的 Importance 或开关状态。实际上 Group 的 API 极其单薄: