当前位置: 首页 > 知识库问答 >
问题:

SharedReferences-活动和广播接收器

邓德惠
2023-03-14

我目前正在使用SharedReferences跟踪通过AlarmManager启动的BroadcastReceiver中要执行工作的项列表。除了一个特定的场景外,一切都很好。当我触发一个新项目来执行工作时,让它完成工作,然后删除该项目(全部通过SharedReferences编辑),它在应用程序运行时工作得很好。当列表中没有任何内容,我打开任务管理器并终止应用程序时,该项突然出现在BroadcastReceiver中(应用程序关闭后仍在运行)。是什么导致了这种行为?我应该在应用程序退出时杀死所有接收器吗?当接收者仍在运行时,关闭活动是否默认返回到另一个SharedReferences对象?

用于从SharedReferences对象中添加/删除项的代码

final SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME,
                Context.MODE_PRIVATE);
final Editor editor = prefs.edit();
mUpdates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, new HashSet<String>());

if (!mUpdates.contains(key)) {
    mUpdates.add(key);
} else {
    mUpdates.remove(key);
}
editor.putStringSet(Config.PREFS_KEY_ACTIVE_TASKS, mUpdates);
editor.apply();

广播接收机代码

public void onReceive(Context context, Intent intent) {
    SharedPreferences prefs = context.getSharedPreferences(Config.PREFS_NAME, Context.MODE_PRIVATE);
    if(prefs.contains(Config.PREFS_KEY_ACTIVE_TASKS)) {
        Set<String> updates = prefs.getStringSet(Config.PREFS_KEY_ACTIVE_TASKS, null);
        if(updates != null) {
            Log.d("RECEIVER","Size="+updates.size());
            for(String key : updates) {
                EntityChangeManager.notifyListeners(key);
            }
        }
    }
}

当我运行代码从初始列表中添加/删除对象时,正如预期的那样,我看到

04-30 20:04:44.165: D/RECEIVER(27079): Size=1
04-30 20:04:44.165: D/RECEIVER(27079): Size=0

当我关闭应用程序时,我看到

04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapUtilization:0.25
04-30 20:04:43.244: D/ActivityThread(27079): setTargetHeapIdealFree:8388608
04-30 20:04:43.254: D/ActivityThread(27079): setTargetHeapConcurrentStart:2097152
04-30 20:04:43.264: D/RECEIVER(27079): Size=1

关注点:

  • 接收器每秒运行
  • 接收器从一个警报管理器启动
  • 声明中没有特殊设置
  • 卸载应用程序后,这是可重复的,清除接收器中的所有首选项(如果它使用不同的)

共有3个答案

公西俊能
2023-03-14

尽管这是一个相对古老的问题,但我还是遇到了同样的问题。对于将来的参考,这可能是有用的。

问题:从BroadcastReceiver检索旧值的位置。这是因为SharedReferences不更新StringSet的内容,因为它是同一个对象

以下内容被更改为通过共享首选项提供持久存储(我不知道哪些东西有助于解决方案):

  • 在清单中,我有android:process=“:remote”,必须将其删除
  • 我使用了上下文。模式多进程作为SharedReferences中的模式(context.getSharedReferences(ref,context.MODE多进程)
  • 最后(因为这篇文章),首先提交一个null值解决了我的问题:
    editor.putStringSet(ref,null);
    editor.commit();
    editor.putStringSet(ref, valuesToBeStored);

我不知道是否需要前两个变化。

韶硕
2023-03-14

如果您在使用StringSet时遇到任何细微差别,那么解决方案是将另一个属性与StringSet本身一起写入SharedReferences对象(如StringSet.size())。原因是SharedReferences库仅将对象与存储的对象进行比较,添加/删除数据不一定会导致对象本身发生更改,因此看起来似乎没有差异。

可以检查对象的大小,如果编辑时对象的大小为0,则只需在将对象保存到SharedReferences之前将其设置为null即可,而不必进行编辑。我选择了第二个SharedRef设置,从那以后它一直运行良好。

季炯
2023-03-14

更改编辑器。应用() 编辑器。提交()。关闭应用程序时,更改可能不会写入磁盘。从官方文件http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()

与将其首选项同步写入持久存储的提交()不同,应用()会立即将其更改提交给内存中的共享首选项,但会启动对磁盘的异步提交,并且不会收到任何失败通知。如果这个共享偏好的另一个编辑器在应用程序()仍然未完成的情况下执行常规提交(),则提交()将阻塞,直到所有异步提交以及提交本身完成。

 类似资料:
  • (与我刚刚发布的另一个问题略有不同,如果这违反了规则,请道歉) 在我的活动1中,我正在设置一些共享首选项,接下来我将通过意图启动另一个活动2,并从中设置一些文本视图。。。这一切都很好。 这就是我的问题。在我的第一个活动1中,我有一个带有挂起意图的警报管理器,这个挂起意图是一个用于锁定手机的广播接收器,然后启动活动2。这个活动和上面提到的第二个活动是一样的。但是,当此活动从启动时,没有任何文本视图从

  • 问题内容: 有人可以解释和之间的确切区别吗? 在什么情况下我们必须使用每个Receiver类? 问题答案: 和之间只有一个区别。 当您收到内部广播方法时, 假设, BroadcastReceiver : 它 不保证 该 CPU将保持清醒 ,如果你启动一些长时间运行的进程。CPU可能会立即回到睡眠状态。 WakefulBroadcastReceiver : 这是 保证 该 CPU将保持清醒 ,直到你

  • 我需要一些帮助来理解当我可以期望我的广播接收器在清单中注册时工作,而不是必须从正在运行的活动或服务中注册。 因此,例如,如果我用以下意图筛选器注册了一个独立的接收器,那么它在没有对它的服务/活动引用的情况下就能正常工作: 但是,如果将替换为,则不会触发接收器(Android文档) 从我在这个站点上发现的,你必须从一个已经运行的活动或服务中注册这个接收器,以使其工作(Post)。 > 有人能告诉我,

  • 本文向大家介绍Android中的广播和广播接收器代码实例,包括了Android中的广播和广播接收器代码实例的使用技巧和注意事项,需要的朋友参考一下 BroadcastReceiver不仅可以接收系统广播,也可接收自定义的广播   1.定义一个广播接收器   2.发送广播,定义好action标志,用Intent发送 3.注册只接收指定action的广播接收器 4.取消该广播接收器

  • 每当它收到消息时,它都会在后台运行,即使应用程序没有运行,它也应该从后台启动活动

  • 我使用Sharedprefs将一个变量从接收者传递到活动。它似乎是正确的,如果我关闭并重新启动应用程序,我可以看到接收器已写入Sharedprefs和活动可以读取最后写入的值。但当应用程序运行时,变量不会更改。它不会从接收器获取值。 这是我的代码从接收器: 这是活动的代码: 那怎么了?为什么接收器不能在应用程序关闭前写入? 顺便说一句,我还在同一个应用程序中的一个单独的服务上读取这个共享的pref