You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何每次修改SharedPreferences都会触发FileObserver多类事件?

问题:SharedPreferences.apply()为何同时触发FileObserver的CREATE、MODIFY、DELETE事件?

我实现了一个继承自FileObserver的自定义类,监听应用内部存储的shared_prefs目录。但每次执行以下代码时:

this.getSharedPreferences("fs_myfilename_", MODE_PRIVATE).edit().putString("Default", "value" + System.currentTimeMillis()).apply();

都会触发FileObserver.CREATE、FileObserver.MODIFY和FileObserver.DELETE事件。

我原本预期:首次写入触发CREATE事件,后续操作仅触发MODIFY事件,想知道为什么实际会同时触发多个事件。


更新内容:代码与日志

自定义FileObserver代码

public SharedPrefObserver(String path) { // 继承自FileObserver的类
    super(path);  
}

// 初始化与启动监听
mSharedPrefObserver = new SharedPrefObserver(getContext().getDataDir() + "/shared_prefs");
mSharedPrefObserver.startWatching();

onEvent重写方法

@Override
public void onEvent(int event, @Nullable String path) {

    if (event == FileObserver.DELETE || event == FileObserver.CREATE || event == FileObserver.MODIFY) {

        Log.e(TAG, "Types of event: \n" +
                "1. Create: " + FileObserver.CREATE + "\n" +
                "2. Modify: " + FileObserver.MODIFY + "\n" +
                "3. Delete: " + FileObserver.DELETE + "\n"
        );

        Log.e(TAG, "onEvent called for the event: " + event + "\n" + "path: " + path);          
    }
}

事件日志(仅监听CREATE、MODIFY、DELETE)

2023-10-13 05:50:27.161  2867-2953  SharedPrefObserver      com.example.app          E  Types of event:  
                                                                                                    1. Create: 256
                                                                                                    2. Modify: 2
                                                                                                    3. Delete: 512                                                                                           
2023-10-13 05:50:27.160  2867-2953  SharedPrefObserver      com.example.app           E  onEvent called for the event: 256
                                                                                                    path: fs_myfilename_.xml
2023-10-13 05:50:27.161  2867-2953  SharedPrefObserver      com.example.app          E  Types of event: 
                                                                                                    1. Create: 256
                                                                                                    2. Modify: 2
                                                                                                    3. Delete: 512
2023-10-13 05:50:27.161  2867-2953  SharedPrefObserver      com.example.app          E  onEvent called for the event: 2
                                                                                                    path: fs_myfilename_.xml

2023-10-13 05:50:27.172  2867-2953  SharedPrefObserver      com.example.app          E  Types of event: 
                                                                                                    1. Create: 256
                                                                                                    2. Modify: 2
                                                                                                    3. Delete: 512
2023-10-13 05:50:27.172  2867-2953  SharedPrefObserver      com.example.app          E  onEvent called for the event: 512
                                                                                                    path: fs_myfilename_.xml.bak

解答

这是因为Android系统中SharedPreferences的apply()方法采用了临时文件写入+原子替换的实现逻辑,具体流程如下:

  1. 创建临时文件写入新内容:每次调用apply()时,系统不会直接修改原fs_myfilename_.xml文件,而是先创建临时文件写入新配置——这会触发CREATE和MODIFY事件(日志中显示的fs_myfilename_.xml事件实际对应临时文件的操作)。
  2. 备份原文件:写入完成后,系统将原文件重命名为fs_myfilename_.xml.bak作为备份。
  3. 替换原文件:把临时文件重命名为原文件名,完成配置更新。
  4. 删除备份文件:最后系统删除.bak备份文件,触发DELETE事件。

这种设计是为了保证SharedPreferences的原子性:即使写入过程中发生崩溃,原文件或备份文件至少有一个是完整的,避免配置文件损坏。

如果只想关注用户实际修改配置的动作,可以通过过滤文件后缀(忽略.tmp和.bak文件),或者结合事件的时间顺序来判断一次完整的apply()操作完成时机。


内容的提问来源于stack exchange,提问作者Ghostop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:39:51