在多进程模式下使用 SharedPreferences

Use SharedPreferences on multi-process mode

我定义了一个用于多进程模式的 SharedPreferences 实例。

public class Prefs {

    private static SharedPreferences prefs;
    private static SharedPreferences.Editor editor;

    private static void init(Context context) {

        prefs = context.getSharedPreferences("alaki",
                Context.MODE_MULTI_PROCESS);
        editor = prefs.edit();
    }

// static methods to set and get preferences
}

现在,我在具有单独进程的服务上使用此 class,也在我的主应用程序进程中以静态方式使用。
一切顺利,但有时所有存储在 SharedPreferences 实例上的数据都被删除了!
我该如何解决这个问题?

编辑: 最后我用 IPC 解决了我的问题。

如果两个进程向 SharedPreferences 写入数据,则可能所有 SharedPreferences 都重置为默认值。

您也可以尝试在存储 val

之前在编辑器上调用 clear()
SharedPreferences.Editor sp = settings.edit();
sp.clear();
sp.putString("Name", "YourName");
sp.commit();

使用 commit() 方法将更改存储在持久存储中,因此它很慢并且会在来自其他进程的多个调用之间产生冲突。

不过这个方法还有一个替代方法,你应该调用apply()方法,这个方法先把变化先存到内存再存到磁盘,比较可靠。

回顾一下,使用上下文对象作为静态字段,你有上下文泄漏的风险,因为没有在应用程序中声明对象class

public class CustomApplication extends Application{
     private Prefs prefs;

     public void onCreate(){
          prefs = new Prefs(this);
     }

     public Prefs getPrefs(){
        return prefs;
     }
}

您可以从任何上下文中获取偏好

   ((MyApplication)context.getApplicationContext()).getPrefs();

SharedPreferences 本身不是进程安全的。这可能就是为什么 SharedPreferences documentation

注意:目前这个class不支持跨进程使用。这个以后补上。

目前无法在多个进程上安全访问 SharedPreferences,如其 documentation 中所述。

Note: This class does not support use across multiple processes.

在使用 MODE_MULTI_PROCESS 进行了大量测试后,我分享了三个试验:

1- 每个进程初始化一次SharedPreferences并多次使用

问题:值没有按预期反映在每个进程中。所以每个进程都有自己的SharedPreferences值。

2- 在每个 put 或 get 中初始化 SharedPreferences

这确实有效,现在该值可以在进程之间互换。

问题: 有时在积极访问 sharedpref 后,共享首选项文件及其所有内容都被删除,如 issue 中所述,我明白了日志中的警告:

W/FileUtils﹕ Failed to chmod(/data/data/com.hegazy.multiprocesssharedpref/shared_prefs/myprefs.xml): android.system.ErrnoException: chmod failed: ENOENT (No such file or directory)

您可以在问题中找到发生这种情况的原因。

3- 使用同步锁定在SharedPreferences.

中放入和获取值的方法

这是完全错误的;同步不适用于跨进程。 SharedPreferences 的实现实际上是使用了同步,但这只保证了线程安全,并没有保证进程安全。这个描述的很好here.

我通过结合解决了这个问题:

  • 为每个进程提供对 SharedPreferences 文件的互斥访问(例如使用 a socket-based locking mechanism
  • 每次您想使用它来绕过内存缓存时,使用 MODE_MULTI_PROCESS 标志重新初始化 SharedPreferences

这似乎工作正常,但尚未在现实​​世界中进行彻底测试,所以我不知道它是否完全可靠。

你可以看到我写的一个工作示例 here

警告:看起来 MODE_MULTI_PROCESS 已在 Android M 中弃用。它可能会在未来停止工作。

使用使用 SharedPreferences 的 Content Provider。示例见此处:https://github.com/hamsterksu/MultiprocessPreferences