在多进程模式下使用 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
我定义了一个用于多进程模式的 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