我在我的android应用程序中使用SharedPreferences。我同时使用commit()和apply()方法共享首选项。当我使用avd2.3时,它显示没有错误,但当我在avd2.1中运行代码时,apply()方法显示错误。

这两者有什么区别呢?通过只使用commit()我可以存储首选项值没有任何问题吗?


当前回答

我使用apply()而不是commit()遇到了一些问题。正如前面在其他响应中所述,apply()是异步的。我得到的问题是,形成一个“字符串集”偏好的变化从来没有写到持久内存。

如果你“强制扣留”程序,或者在我安装在Android 4.1设备上的ROM中,由于内存需求进程被系统杀死,就会发生这种情况。

如果你想激活你的首选项,我建议使用“commit()”而不是“apply()”。

其他回答

commit()和apply()的区别

当我们使用SharedPreference时,我们可能会被这两个术语混淆。基本上它们可能是相同的,因此让我们澄清commit()和apply()的区别。

1.返回值:

Apply()提交时不返回表示成功或失败的布尔值。 如果保存有效,Commit()返回true,否则返回false。

速度:

Apply()更快。 Commit()比较慢。

异步vs .同步:

应用():异步的 commit():同步

原子性:

应用():原子 commit():原子

错误通知:

应用():没有 commit():是的

使用适用于()。

它立即将更改写入RAM,然后等待并将其写入内部存储(实际的首选项文件)。Commit同步且直接地将更改写入文件。

我使用apply()而不是commit()遇到了一些问题。正如前面在其他响应中所述,apply()是异步的。我得到的问题是,形成一个“字符串集”偏好的变化从来没有写到持久内存。

如果你“强制扣留”程序,或者在我安装在Android 4.1设备上的ROM中,由于内存需求进程被系统杀死,就会发生这种情况。

如果你想激活你的首选项,我建议使用“commit()”而不是“apply()”。

Commit()是同步的,apply()是异步的 Apply()是void函数。 如果新值成功写入持久存储,Commit()返回true。 apply()保证在切换状态之前完成,你不需要担心Android组件的生命周期

如果你不使用commit()返回的值,而你在主线程中使用commit(),请使用apply()而不是commit()

在使用web API时,我注意到apply()在注销前使用共享首选项时的主要缺点。

请看下面的场景: 用户登录和令牌(用于自动重新登录)随POST一起传递。

SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", Context.MODE_PRIVATE);

SharedPreferences.Editor editor = preferences.edit();

editor.putString("TOKEN",token);

editor.apply();

令牌在所有会话中都可用,没有问题,自动重新记录在整个状态中没有任何进一步的问题。

在编写注销函数时,我清除了共享首选项,如下所示

SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", Context.MODE_PRIVATE);

SharedPreferences.Editor editor = preferences.edit();

editor.clear();

editor.apply()

简而言之,你可以这样写:

preferences.edit().clear().apply()

为了确保我清除了缓存,我会在注销前Log,和preferences.getString("TOKEN");显示为null。

在重新启动主活动(因为它是从登录片段开始的)-我会再次检查令牌,使用:

SharedPreferences preferences = App.getContext().getSharedPreferences("UserCredentials", MODE_PRIVATE);
        
String retrievedToken = preferences.getString("TOKEN",null); // Second param = default value

Log.d(TAG, "RETRIEVING TOKEN: " + retrievedToken);

令牌实际上重新出现,即使令牌在注销之前肯定已经被清除。

(导致注销-> '登录-使用-令牌循环)

只有在添加了editor.commit()之后;设置和清除令牌实际上都将永久消失。

注意,我使用了模拟器。

这种行为实际上是有道理的,因为内存中的存储被更新了,但异步调用在应用程序重新启动之前从未进行过。

因此commit ();将迫使应用程序等待(同步)与实际的后续命令,如system.exit()等,而apply()可以很好地失败,如果其他命令将强制应用程序中的某个状态改变。

为了确保你找到了所有正确的点,你可以同时使用apply()和commit()。