目录
1. SharedPreferences 定义介绍
用于访问和修改 context#getSharedPreferences 返回的 preference 数据的接口,如果你想要保存的键值(key-value)集合,且数据量相对较小,这时候使用 SharedPreferences 存储数据比较合适。对 Preference 数据进行修改时必须通过 Editor 对象,以确保 Preference 数据处于一致的状态,并将它们提交到存储中( /data/data/包名/shared_prefs/ )进行控制。
2. SharedPreferences.Editor 方法介绍
用来修改 SharedPreferences 对象值的接口,修改完毕,调用 commit() 或 apply() 方法来提交生效刚所做的修改。
2.1 apply()
void apply(); 没有返回值
异步提交你的改变,来替换当前 SharedPreferences 对象中的任何内容。
注意:如果有两个 Editor 对象同时在修改同一个 Preferences 对象,两个 Editor 谁提交的晚,那么谁的提交有效,也就是说,后面的提交会覆盖之前的提交。
2.2 commit()
boolean commit(); 当新的值成功的存入本地数据库时,返回 true。
同步提交你的改变,来替换当前 SharedPreferences 对象中的任何内容。
注意:如果有两个 Editor 同时修改同一个 preferences 对象,最后一个调用 commit() 方法的 Editor 获胜,其所做的改变生效。
当你不需要关心其返回值并且是在 app 的主线程中使用它时,使用 apply() 方法会更加合适。
2.3 clear()
Editor clear(); 返回 SharedPreferences.Editor 对象
删除 Preferences 中的所有值,因为返回 SharedPreferences.Editor 对象,所以可以将 Editor 的调用方法链接起来使用,比如先 put,然后 clear,再 put:
mEditor.putString("firstAdd", "first add by jere\n")
.clear()
.putString("secondAdd", "second add by jere !")
.apply();
思考一下,执行完该语句,SharedPrefeences 里存取了什么数据?答案见下图:
原因: 在 SharedPreferencers 提交改变之前,无论是在 put 数据方法之前或之后调用 clear() 方法,都会优先执行 clear() 方法。
2.4 remove()
Editor remove(String key); 返回 SharedPreferences.Editor 对象
删除单个指定 key 的 preferences 值,跟 clear() 方法一样,因为返回 SharedPreferences.Editor 对象,所以可以将 Editor 的调用方法链接起来使用。比如接着上方 clear() 的例子,删除“firstAdd”的数据,效果如下所示:
public class FirstActivity extends AppCompatActivity implements View.OnClickListener {
private SharedPreferences mSp;
private SharedPreferences.Editor mEditor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSp = getSharedPreferences("PreferencesName", Context.MODE_PRIVATE);
mEditor = mSp.edit();
Button setBtn = findViewById(R.id.set_btn);
Button removeBtn = findViewById(R.id.remove_btn);
Button getBtn = findViewById(R.id.get_btn);
setBtn.setOnClickListener(this);
removeBtn.setOnClickListener(this);
getBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.set_btn:
mEditor.putString("firstAdd", "first add by jere\n")
.clear()
.putString("secondAdd", "second add by jere !")
.apply();
break;
case R.id.remove_btn:
mEditor.remove("firstAdd").apply();
break;
case R.id.get_btn:
String firstAddString = mSp.getString("firstAdd", "");
String secondAddStrig = mSp.getString("secondAdd", "");
String displayString = firstAddString + secondAddStrig;
TextView displayTv = findViewById(R.id.display_tv);
displayTv.setText(displayString);
break;
default:
break;
}
}
}
2.5 apply() 与 commit() 的区别
commit() 同步写入本地数据库,apply() 会先将改变提交到内存中的 SharedPreferences 中,然后在异步写入本地数据库,即使存入失败了也不会通知你。
特殊情况:当 SharedPreferences 正在执行一个 Editor 的 apply() 操作时,另一个 Editor 对此 SharedPreferences 执行 commit() 操作,这种情况下,因为 apply() 操作还没结束,所以 commit() 操作将被 block 阻止掉,直到 apply() 操作完成。
//所以正确的使用 commit() 方法为:如果 commit 不成功,提醒我们。
if (!editor.commit()) {
Log.e(LOG_TAG, "Failed to commit setting changes");
}
3. SharedPreferences 例子Demo
三种方法创建 SharedPreferences 对象,分别是getSharedPreferences(int mode)、getSharedPreferences(String name, int mode)、getDefaultSharedPreferences(Context context) 三种方法,如下所示:
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.get_pref_btn:
//getPreferences() 方法
SharedPreferences sp = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("JereTest", "first test");
editor.apply();
break;
case R.id.get_shared_pref_btn:
//getSharedPreferences() 方法
SharedPreferences sp1 = getSharedPreferences("testGetSharedPref", MODE_PRIVATE);
SharedPreferences.Editor editor1 = sp1.edit();
editor1.putString("getSharedPref", "test getSharedPreferences!");
editor1.apply();
break;
case R.id.get_default_shared_pref_btn:
//getDefaultSharedPreferences() 方法
SharedPreferences sp2 = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor2 = sp2.edit();
editor2.putString("getDefaultSp", "jere test getDefaultSharedPreferences!");
editor2.apply();
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
break;
default:
break;
}
}
Context.MODE_PRIVATE | 为默认操作模式,其中创建的文件只能被调用应用程序访问,既只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。 |
Context.MODE_APPEND | 模式会检查文件是否存在,存在就往文件末尾追加内容而不是覆盖,否则就创建新文件。 |
Context.MODE_WORLD_READABLE Context.MODE_WORLD_WRITEABLE | 自API level 17就已经弃用,从Android 7.0 (API level 24)开始,如果使用,Android会抛出SecurityException异常。如果您的应用程序需要与其他应用程序共享私有文件,它可以使用带有FLAG_GRANT_READ_URI_PERMISSION的FileProvider。 |
3.1 getPreferences() 例子Demo
如果只需要为一个 Activity 使用一个共享首选项文件(shared preference file),直接在 Activity 中使用 Activity.getPreferences(int mode)。
//因为这将是用于该 Activity 的唯一首选项文件,所以无需提供名称。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
存储的文件将以 Activity 的类名及 xml 格式保存在 /data/data/包名/shared_prefs/ 下,例如:
例子:在同一个activity下进行保存/读取显示数据,同时尝试在不同的 activity 下读取数据。效果如下:
详细代码:
//on MainActivity
//save data
mSetSharedPreferencesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(NAME, mEditText.getText().toString());
editor.apply();
}
});
//retrieve data and display
getSpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
String nameString = sharedPref.getString(NAME, "test by null");
displaySpText.setText(nameString);
}
});
//on SecondActivity
//retrieve data in second activity, the default value is null
SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
contentString = sharedPref.getString(NAME, "null");
// display data
mSharedPreferencesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTextView.setText(contentString);
mTextView.setVisibility(View.VISIBLE);
}
});
3.2 getSharedPreferences() 例子Demo
当你想要保存或检索的数据可以在应用程序中的不同的 Activity 中使用时,或需要通过名称标识多个共享首选项文件时(shared preference file),使用 Context.getSharedPreferences(String name, int mode),可以使用第一个参数指定这些文件。你可以从应用程序的任何Context调用它。
SharedPreferences sharedPref = context.getSharedPreferences("file name", Context.MODE_PRIVATE);
存储的文件将以我们提供的文件并以 xml 格式保存在 /data/data/包名/shared_prefs/ 下,例如我们提供的文件名为“testGetSharedPref”:
例子:两个 activity 之间进行存/取数据,实现数据共享,在MainActivity 中存储文件“testGetSharedPref”,然后跳到 SecondActivity 中读取该文件中的内容,然后显出出来,效果图如下:
详细代码:
//在 MainActivity 中存储数据,文件名为“testGetSharedPref”:
SharedPreferences sharedPref = this.getSharedPreferences("testGetSharedPref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(NAME, "My name is Jere!");
editor.putString(HOBBY, "I like play basketball!");
editor.apply();
mSetSharedPreferencesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//存储“testGetSharedPref”文件后,跳转到 SecondActivity
Intent secondIntent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(secondIntent);
}
});
//在 SecondActivity 中取出 "testGetSharedPref" 文件中的数据并显示出来:
SharedPreferences sharedPref = this.getSharedPreferences("testGetSharedPref", Context.MODE_PRIVATE);
String nameString = sharedPref.getString(NAME, null);
String hobbyString = sharedPref.getString(HOBBY, null);
contentString = nameString + "\n" + hobbyString;
mSharedPreferencesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTextView.setText(contentString);
mTextView.setVisibility(View.VISIBLE);
}
});
3.3 getDefaultSharedPreferences() 例子Demo
可以获得整个应用程序的默认共享首选项文件,通过调用静态方法 PreferenceManager.getDefaultSharedPreferences() 将共享首选项文件保存在应用程序任何 Actiity 都可以访问的位置中。
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
我们不需要额外提供文件名,所存储的文件以我们 App 的包名加 _preferences 并以 xml 的格式保存在 /data/data/包名/shared_prefs/ 下,例如:我们的包名为com.jere.test
实践:EditText() 输入数据,点击set SharedPreferences按钮,保存数据,并且跳转到第二个页面;在第二个页面点就get SharedPreferences按钮,取得数据,并显示出来!效果图如下?:
详细代码如下:
//在 MainActivity 中保存文件
SharedPreferences sp2 = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor2 = sp2.edit();
editor2.putString("getDefaultSp", "jere test getDefaultSharedPreferences!");
editor2.apply();
//然后跳转到 SecondActivity
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
//在 SecondActivity 中读取文件内容并且显示出来
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(SecondActivity.this);
String contentData = sp.getString("getDefaultSp", null);
TextView tv = findViewById(R.id.show_tv);
tv.setText(contentData);
}
});
}
}
4. getPreferences() getSharedPreferences() 及 getDefaultSharedPreferences() 三者区别
虽然三种方法创建的文件都是以 xml 的格式存储在 /data/data/包名/shared_prefs/ 下,但其文件名还是有很大区别的,如下图所示:
- 1号文件由 Activity.getPreferences(int mode) 方法创建,存储的文件以 Activity 名字(Java 类名不带后缀)命名。
- 2号文件由 PreferenceManager.getDefaultSharedPreferences(Context context) 方法创建,存储的文件以 App 的包名加上 _preferences 命名。
- 3号文件由 Context.getSharedPreferences(String name, int mode) 方法创建,存储的文件以传入的 name 参数命名。
getPreferences() 只能在当前页面(同一个activity)之间进行数据存取,若想在多个 activity 中共享数据,需要使用getSharedPreferences() 或 getDefaultSharedPreferences()。
END~~