SharedPreference
SharedPreference 当存储 UI 状态、用户首选项、应用程序设置时,我们需要一种轻量级机制以存储一个已知的值集。SharedPreference 能够保存一组原始数据的名、值对保存为命名的首选项。
已保存的应用程序 UI 状态 当应用程序移动到后台时,Activity 和 Fragment 会包含专用的事件处理程序以记录当前的 UI 状态
文件 Android 使我们能够在设备的内部或外部媒体上创建并加载文件,它作为临时缓存提供了支持,并将文件存在公用可访问的文件夹中。
创建并保存 SharedPreference
使用 SharedPreference 类可以创建名称/值对,他们可以在会话之间持久化,并在同一个应用程序沙箱中运行的组件之间共享。
SharedPreference 存储在应用程序的沙箱中,所以可以在应用程序组件之间共享,但是对其他应用程序来说不可用。
在Android系统中, 其配置文件的数据文件 以XML文件的形式保存在 /data/data/PACKAGE_NAME/shared_prefs
目录下
创建 SharedPreference:SharedPreferences preferences = getSharedPreferences("Jack", Activity.MODE_PRIVATE);
Context context = getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
修改 SharedPreference:SharedPreferences.Editor editor = preferences.edit();
插入或更新 SharedPreference:
editor.putString("TextName", "Jack");
editor.putInt("last", 1);
保存编辑的动作:
// 异步保存
editor.apply();
// 同步保存
editor.commit();
查询 SharedPreference
使用类型安全的 get<Type>
方法来提取已保存的值,每个 getter 都接受一个键和一个默认值。
也可以通过 getAll
返回所有的 SharedPreference 键值的一个映射。通过调用 contains
方法可以查询特定的键是否存在。
首选项框架和 Preference Activity
Android 中提供了一个 XML 驱动的框架,用来为应用程序创建系统样式的 Preference Screen。通过使用该框架,能够确保应用程序中的 Preference Activity 与本地和其他第三方应用程序中所使用的一致。
Preference Activity 框架由下面 5 部分组成:
Shared Preference Change Listener
一个 onSharedPreferenceChangeListener
类的实现,用于监听 SharedPerference 的变化。每当添加、删除或修改一个特定的 SharedPreference 时来回调该函数。
Preference Screen布局
一个布局控制文件,它指定了要显示的文本和相关控件、所允许的值和为每个空间使用的 SharedPreference 键。定义XML文件在 res/xml
目录下。
Preference Screen 文件包含以下几个元素组成:
- android:key 在 Shared Preference 中保存的键
- android:title 标题
- android:summary 描述信息
- android:defaultValue 默认值
- android:entries 对应的选项列表
- android:entrieValues 对应的选项列表的值
- android:dialogTitle 弹出的列表的 Dialog 的 title
Preference Screen 文件包含以下几种控件类型:
- ListPreference 单选列表对话框的控件
- CheckBoxPreference 一个标准的首选项复选框
- EditTextPreference 允许用户输入一个字符串作为一个首选项
- MultiSelectListPreference 在 API Level 11 中引入的,类似于复选框列表
- RingtonePreference 一个专用的列表首选项,显示可供用户选择的可用铃声列表
- SwitchPreference 开关状态选择控件
此外也可以通过扩展 Preference 类 或上述控件来创建属于自己的首选项控件。
Preference Fragment:
是从 API Level 11 之后才添加进来的,用来包含 Preference Screen 资源定义。需要继承此类来创建一个新的 Preference Fragment。
为 Preference Fragment 填充首选项,需要重写 onCreate 方法,并调用 addPreferencesFromResource
方法
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.userpreferences);
}
Preference Header 定义
Preference Header 是 XML 资源,存在 res/xml
文件夹下,每个资源文件名称就是它的 ID,每个 Preference Header 必须关联一个 Preference Fragment,必须指定 Preference Header 的标题。还可以选择一个 图标。
对于不同的屏幕尺寸版本,用于显示头及其相关 Fragment 的布局也可能不同。
Preference Activity
Preference Activity 类用于包含由 Preference Header 资源定义的 Preference Fragment 层次结构。在 Android 3.0 之前,Preference Activity 用于直接包含 Preference Screen。如果在 Android 3.0 之前运行,则还是需要直接使用 Preference Activity。
当需要使用 Preference Fragment 和 Preference Header 时,需要重写 onBuildHeaders
处理程序,在其中调用 loadHeadersFromResources
并指定一个 Preference Header 资源文件:
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
当装载 Preference Fragment 和 Preference Header 时,重写 onCraete
处理程序,在其中调用 addPreferencesFromResource
方法:
public void onCreate(Bundle savedInstanceState) {
addPreferencesFromResource(R.xml.preference_headers);
}
最后像所有 Activity 程序一样,在 manifest 文件中添加 activity
通过 Intent 导入系统的首选项,把系统首选项显示内容添加到 preference screen 中
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<intent android:action="android.settings.DISPLAY_SETTINGS" />
</PreferenceScreen>
Preference Fragment 和 Preference Header 是在 Android API Level 11 中才被引入的,低于 API 11 版本的将不会被支持,因此要做一些处理,让低于 11 版本的 API 继续使用 Preference Activity。
Class c = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? UserPreferencesActivity.class : FragmentPreferences.class;
Intent i = new Intent(this, c);
持久化应用程序实例状态
如果你想要保存并不需要与其他组件共享的 Activity 信息(类实例变量),那么可以调用 Activity.getPreferences(),而不需要指定一个 SharedPreference 名称,这会返回一个 SharedPreference,其名称就是调用 Activity 的名称。
// 创建或检索 Activity 首选项对象
SharedPreferences sharedPreferences = this.getPreferences(Activity.MODE_PRIVATE);
使用生命周期处理程序保存和还原 Activity 实例
Activity 提供了 onSaveInstanceState 处理程序来保存与会话之间的 UI 状态关联数据,如果 Activity 是由用户关闭的(或按下 onBack 按键)或调用 finish 关闭的。那么下一次创建 Activity 时,实力状态 Bundle 是不会传递给 onCreate 和 onRestoreInstanceState。
通过重写一个 Activity 的 onSaveInstanceState 事件处理程序,可以使用它的 Bundle 参数来保存 UI 实例的值。每当 Activity 完成了生命周期,但是还没有被显式的结束(调用 finish)时,该处理程序将会触发。
protected void onSaveInstanceState(Bundle saveInstanceState) {
// 检索视图
TextView textView = (TextView) findViewById(R.id.title);
// 保存状态
saveInstanceState.putString(TEXTVIEW_STATE_KEY, textView.getText().toString());
super.onSaveInstanceState(saveInstanceState);
}
如果应用程序被强制重启,那么已保存的 Bundle 参数就会被传入 onRestoreInstanceSave 和 onCreate 方法中。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.title);
String text = "";
if (savedInstanceState != null && savedInstanceState.containsKey(TEXTVIEW_STATE_KEY))
text = savedInstanceState.getString(TEXTVIEW_STATE_KEY);
textView.setText(text);
}
使用生命周期处理程序保存和还原 Fragment 实例状态
大多数应用程序的实例都封装在 Fragment 内,Fragment 也包含一个 onSaveInstanceState 处理程序,其工作方式与 Activity 中的对应处理程序十分相似。
持久化到 Bundle 中的实例状态作为参数传递给 Fragment 的 onCreate、onCreateView 和 onActivityCreated 处理程序。
在 Activity 被销毁然后被重新启动,以及处理硬件配置改变的情况下,可以请求保存 Fragment 的状态。设置 Fragment 的 onCreate 处理程序内的 setRetainInstance 方法为 true
之后,当 Activity 被重新创建时,Fragment 的实例不应该被终止和重新启动。
因此,当设备配置改变,并且 Activity 被销毁和重新创建时,Fragment 的 onDestroy 和 onCreate 不会被调用。如果将大部分对象创建代码移入 onCreate,同时使用 onCreateView 和已保存的实例值中存储的值来更新 UI,这样可以显著的提交效率。
public static class PlaceholderFragment extends Fragment {
private static final String USER_SELECTION = "";
private int userSelection = 0;
private TextView tv;
public PlaceholderFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
if (savedInstanceState != null) {
userSelection = savedInstanceState.getInt(USER_SELECTION);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
tv = (TextView) rootView.findViewById(R.id.text);
setSelection(userSelection);
Button button1 = (Button) rootView.findViewById(R.id.button1);
Button button2 = (Button) rootView.findViewById(R.id.button2);
Button button3 = (Button) rootView.findViewById(R.id.button3);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSelection(1);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSelection(2);
}
});
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSelection(3);
}
});
return rootView;
}
private void setSelection(int selection) {
userSelection = selection;
tv.setText("Selected: " + selection);
}
@Override
public void onSaveInstanceState(Bundle saveInstanceState) {
saveInstanceState.putInt(USER_SELECTION, userSelection);
super.onSaveInstanceState(saveInstanceState);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。