☰
Once实战避坑清单:忘记initialise、tag命名规范、static import等6个常见错误排查
2026/10/14 16:19:39 网站建设 项目流程

【免费下载链接】Once

A small Android library to manage one-off operations.

项目地址:https://gitcode.com/gh_mirrors/onc/Once
点击查看免费下载

Once 是一个管理 Android 一次性操作的轻量级开源库:引导页只弹一次、升级说明每个版本只提示一次、接口每小时最多上报一次。本文基于源码和官方示例,整理出 6 个最常见的错误与排查方法,帮你快速定位 Once 不生效或行为异常的问题。

快速上手:2步完成 Once 初始化

安装依赖(需mavenCentral()仓库,注意 1.3.1 起已迁移出 jcenter):

dependencies { implementation 'com.jonathanfinerty.once:once:1.3.1' }

然后在 Application 类的onCreate()中初始化,并记得在 Manifest 中注册:

public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); Once.initialise(this); } }

参考官方示例 ExampleApplication.java 和 AndroidManifest.xml(android:name=".ExampleApplication")。

坑1:忘记调用 Once.initialise(),触发 NullPointerException ⚠️

initialise(this)必须在任何beenDone、markDone调用之前执行。它负责创建持久化存储并读取 App 更新时间:

public static void initialise(Context context) { tagLastSeenMap = new PersistedMap(context, "TagLastSeenMap"); toDoSet = new PersistedSet(context, "ToDoSet"); ... }

源码见 Once.java。

  • 现象:App 启动即崩溃,堆栈指向tagLastSeenMap.get(tag)处的 NPE。
  • 排查:确认初始化代码是否真的执行了——最常见原因是 Application 子类没在AndroidManifest.xml中注册,onCreate()根本没被调用。

坑2:scope 选错——THIS_APP_INSTALL 与 THIS_APP_VERSION 混用

Once 提供三种作用域常量:

常量含义
THIS_APP_INSTALL整个安装周期只执行一次
THIS_APP_VERSION每个 App 版本执行一次
THIS_APP_SESSION当前进程会话执行一次

最典型的错误:升级说明弹窗用了THIS_APP_INSTALL,导致用户升级后永远看不到新版本的 WhatsNew。正确写法见 README.md。

两个易踩的细节:

  1. 单参数beenDone(tag)默认是THIS_APP_INSTALLscope,不是一般的"本次会话":

    // 实际等价于 beenDone(THIS_APP_INSTALL, tag, moreThan(0)) public static boolean beenDone(String tag)

    见 Once.java。

  2. THIS_APP_SESSION只存在于内存,进程被杀后自动清零,且该 scope 不能用于toDo(scope, tag)的持久化判断。

坑3:tag 命名不规范——同一个操作变成两个"陌生人"

Once 的所有状态都由字符串 tag 索引,tag 拼错一个字母,检查与打标记就对不上了,表现为"每次都弹"或"从不弹"。官方示例的规范做法是把 tag 定义为常量:

private static final String SHOW_NEW_VERSION_DIALOG = "NewVersionDialog"; private static final String SHOW_MINUTE_DIALOG = "OncePerMinuteDialog";

见 MainActivity.java。

  • 排查技巧:全局搜索 tag 字符串,确认markDone(xxx)与beenDone(xxx)用的是同一个常量。
  • 避免两个不相关的功能复用同一个 tag——它们会共享完成状态。
  • 建议命名风格统一(如驼峰 + 功能语义),NewVersionDialog而不是v2、new。

坑4:static import 用错位置或漏导 Amount

README 推荐用 static import 精简代码:

import static jonathanfinerty.once.Amount.exactly; import static jonathanfinerty.once.Once.THIS_APP_INSTALL; import static jonathanfinerty.once.Once.beenDone; import static jonathanfinerty.once.Once.markDone;

见 MainActivity.java。常见错误有三种:

  1. 漏导Amount的方法:直接写exactly(3)会报cannot find symbol,因为它属于Amount类而非Once类(见 Amount.java)。
  2. 常量与方法混淆:THIS_APP_VERSION是静态常量、beenDone是静态方法,两者都可以 static import,但别以为导入类Once就包含了Amount里的方法。
  3. 只导了一部分:导了markDone却漏了beenDone,编译时才发现。要么全部 static import,要么统一用Once.xxx前缀,保持文件内一致。

坑5:markDone 时机错误——忘记调用或先标记后检查

Once 本身不做任何事,全靠你手动打标记。标准模式是"先检查,执行操作,最后 markDone":

if (!beenDone(Once.THIS_APP_VERSION, showWhatsNew)) { startActivity(new Intent(this, WhatsNewActivity.class)); Once.markDone(showWhatsNew); // 成功后再标记 }
  • 忘记markDone:操作每次都执行,Once 形同虚设。
  • 在if外提前标记:判断和标记之间逻辑脱节,可能出现标记了但操作没执行。
  • 另外,markDone(tag)会自动把该 tag 从 to-do 集合中移除,所以toDo(tag)之后调用markDone(tag)即可完成任务闭环,不需要手动clearToDo。见 Once.java 和 ToDoTests.java。

坑6:exactly(n) 语义混淆——计数满 3 次后永远不再触发

想"用户用了 3 次核心功能后提示评分",很多人写成beenDone(tag, exactly(3))然后困惑为什么第 4 次点击没反应——exactly(3)表示"恰好等于 3 次",计数到 4、5 次时判断为false:

markDone("action"); if (beenDone("action", exactly(3))) { showRateTheAppDialog(); }

对应源码return count -> numberOfTimes == count;(见 Amount.java)。测试用例 OnceTests.java 验证了该行为。

解决方案:

  • 只需触发一次 → 改用Amount.moreThan(2)(≥3 次);
  • 需要循环计数(每 3 次一次)→ 触发后调用clearDone(tag)重置计数,官方示例即采用此做法:
String buttonPressedTag = "button pressed"; markDone(buttonPressedTag); if (beenDone(buttonPressedTag, exactly(3))) { showDialog("This dialog should only appear once every three presses"); clearDone(buttonPressedTag); // 重置计数,进入下一轮 }

见 MainActivity.java。

附:调试与重置速查

需求API
重置单个 tagclearDone(tag)/clearToDo(tag)
清空全部记录clearAll()
查最近完成时间(未完成返回 null)lastDone(tag)
时间窗口限频beenDone(TimeUnit.HOURS, 1, tag)

💡 调试时最省事的办法是示例 App 里的"Reset All"按钮:直接调用Once.clearAll()(见 MainActivity.java)。

Once 的 API 很小,出问题基本都出在初始化时机、scope 选择、tag 一致性、标记时机这四件事上。对照本清单逐项排查,绝大多数"Once 不工作"的现象都能迎刃而解。

【免费下载链接】Once

A small Android library to manage one-off operations.

项目地址:https://gitcode.com/gh_mirrors/onc/Once
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询