我在我的android应用程序中使用SharedPreferences。我同时使用commit()和apply()方法共享首选项。当我使用avd2.3时,它显示没有错误,但当我在avd2.1中运行代码时,apply()方法显示错误。
这两者有什么区别呢?通过只使用commit()我可以存储首选项值没有任何问题吗?
我在我的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()。