【问题标题】:SharedPreferences reads old valuesSharedPreferences 读取旧值
【发布时间】:2012-12-17 04:13:36
【问题描述】:

我使用 SharedPreferences 在我的应用程序的不同活动中写入和稍后读取值。 它过去可以正常工作,但最近它似乎没有被sincronized。我的意思是,我写了一个值,但其他活动仍然读取旧值。 有时它可以正常工作。 有什么想法吗?

编辑: 这是一个示例代码:

首先,来自一个线程:

SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("ComandToDo", value);
editor.commit();
... some code later:
alarmmanager.set(AlarmManager.RTC_WAKEUP, Miliseconds, sender);

在报警接收器中:

SharedPreferences prefs = contexto.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
int value = prefs.getInt("ComandToDo", -1);    

问题来了,因为“值”不是线程中写入的值。

【问题讨论】:

  • 你是在不同的线程中进行这些读写吗?把代码贴在你读写的地方。
  • 是的,不同的线程、活动、广播接收器……很多地方。想象一下:一个线程在 SharedPreferences 中写入一个值。然后它会创建一个警报。广播接收器在几分钟后读取该值。但是没有更新!
  • 需要查看您的代码在哪里读取和写入值。
  • SharedPreferences 是线程安全的,但不是进程安全的。如果您已将应用设置为使用多个进程,则可能会遇到此问题。在这种情况下,最简单的解决方案是摆脱多个进程。
  • 如果我更改数据库中表的 SharedPreferences 会遇到同样的问题吗?

标签: android sharedpreferences


【解决方案1】:
  1. SharedPreferences 被记录为不能跨进程工作,http://developer.android.com/reference/android/content/SharedPreferences.html,“注意:目前此类不支持跨多个进程使用。稍后将添加。”

  2. 此答案建议将数据封装到内容提供程序中,并且讨论还考虑了一些其他选项,包括共享 SQLite:https://stackoverflow.com/a/5265556/1665128

  3. 文件系统中还有普通的旧文件。我们在几个项目中使用了它们,带有锁定,没有任何问题。也可能是您的一个选择。

【讨论】:

  • 谢谢!还有一个问题。这并不是真正的两个进程相互踩踏。它只是一个记录要做的事情并触发和警报的线程(可能几个小时后)。就这么简单!那么,有没有办法强制写入磁盘并保留缓存?谢谢
  • @Ton:移动系统不尽快提交东西确实看起来很奇怪。以防万一,尽管如此简单,但它可能是一个逻辑错误吗?一些疯狂的事情,比如第三段代码碰巧覆盖了提交,控制以某种方式没有到达保存点(“稍后一些代码”中的一个例外)等等。用 Log.d 来点缀它怎么样? (此外,查看 Android 代码会很有趣;我现在手头没有任何东西,但是,AFAIK,在幕后,这些首选项保存在文件中。)
  • 在撰写本文时SharedPreferences 仍然说“注意:目前此类不支持跨多个进程使用。稍后将添加。”但是,API 11 添加了MODE_MULTI_PROCESS,其中“设置后,即使共享首选项实例已在此过程中加载,也会检查磁盘上的文件是否修改......”因此,您应该能够使用getSharedPreferences(PREFS_NAME, Context.MODE_MULTI_PROCESS)
【解决方案2】:

您正在写入“MyPrefs”首选项文件,然后尝试从“PerfilDeSonidoPreferencias”文件中读取。请从同一个首选项文件中读/写。

【讨论】:

  • 对不起,这只是复制粘贴时的错误。两者都是“MyPrefs”之类的。
【解决方案3】:

这是我遇到的情况以及我为解决它所做的工作。

我正在从 Activity 触发警报,并且在该警报的 Broadcast-Receiver 中,我正在更新每次启动应用程序时都会读取的 Shared-Preferences。

触发警报后,每当启动应用程序时,它都会获取仅从该活动设置的旧值。没有反映来自广播接收器的更改。

这里的技巧是将 Shared-Preferences 设置为 MODE_MULTI_PROCESS

一般我们使用MODE_PRIVATE,但是如下:

SharedPreferences prefs = this.getSharedPreferences("Preferences", MODE_MULTI_PROCESS);

注意:在代码中更改模式后,建议清除应用程序的数据以避免调试时出现问题。

编辑: MODE_MULTI_PROCESS 需要最少 API 11

在 API 11 之前,我能想到的解决方法是创建一个包含 2 列 KEY 和 VALUE 的数据库。 这可以从其他模块访问。

【讨论】:

  • 谢谢,但我认为您至少需要 API 11 来完成这项工作
  • 哦,是的。抱歉,忘记提了。
  • 文档说现在不要使用它,因为它已被弃用,因为它工作不可靠。
【解决方案4】:

只需使用 IntentService 代替 BroadcastReceiver。这对我有用。

服务类:

public class ServiceClass extends IntentService {

    public NotificationPopupService(String name) {
        super(name);
    }

    public NotificationPopupService(){
        super("YOU_DEFAULT_NAME");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        do magic...
    }
}

在您的 AndroidManifest.xml 文件中的应用程序标记中:

<service android:name="ServiceClass"/>

创建警报:

intent = new Intent(context, ServiceClass.class);
pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// magic after 2 seconds after the creation of alarm
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2012-05-05
    相关资源
    最近更新 更多