三种技术:preference、本地文件和SQLite
一、Android中的数据保存技术:
共享的preference
文件
SQLite数制库
内容提供器
共享的preference
二、保存简单的应用程序数据
两种轻量级技术:共享的preference和用来保存活动实例细节的一对事件处理程序
用SharedPreference在应用程序中创建命名的键/值映射
活动提供SaveInstanceState处理程序,参数Bundle代表一个基本的键/值映射,其后这一参数传给OnCreate和onRestoreInstanceState方法处理程序,用以记录活动(Activity)需要的值
1、创建和保存preference
上下文调用getSharedPreference
SharedPreference.Editor类:修改一个共享preference。用法:在SharedPreference上调用edit得到一个编辑器对象,保存编辑,只需调用编辑器commit即可。
2、检索共享的Preference
使用getSharedPreference访问已经保存的共享Preference,通过传递给它希望访问的共享Preference的名称,并使用类型安全的get<type>方法来提取已保存的值
3、保存活动状态
Activity.getPrefrence():不指定名字,保存不需要和其它组件进行共享的活动信息(如类实例变量)。
如何使用活动的私有共享Preference:
1: protected void saveActivityPreference(){
2: // 创建或者检索活动的preference
3: SharedPreferences activityPreference = getPreferences(Activity.MODE_PRIVATE);
4: //找一个编辑器来修改共享的preference
5: SharedPreferences.Editor editor = activityPreference.edit();
6:
7: //检索View
8: TextView myTextView=(TextView)findViewById(R.id.myTextView);
9:
10: // 在共享的Preference对象中存储新的原语类型
11: editor.putString("currentTextValue", myTextVIew.getText().toString());
12: //提交修改
13: editor.commit();
14: }
⑴ 保存和恢复实例状态
重写onSaveInstanceState事件处理程序,用其参数Bundle参数来保存实例的值。使用相同的get和set方法对共享的preferenct的值进行存储,然后把修改过的Bundle传给超类的处理函数
1: private static final String TEXTVIEW_STATIC_KEY = "TEXTVIEW_STATIC_KEY";
2: @Override
3: public void onSaveInstanceState(Bundle outState){
4: //检索View
5: TextView myTextVIew = (TextView)findViewById(R.id.myTextView);
6: //保存它的状态
7: outState.putString(TEXTVIEW_STATIC_KEY, myTextView.getText().toString());
8: super.onSaveInstanceState(outState);
9: }
onRestoreInstanceState在一次会话被强制重启时触发,Bundle会传递到其onCreate方法中。下列展示如何从Bundle中提取值,用它来更新活动的实例状态
1: @Override
2: public void onCreate(Bundle icicle) {
3: super.onCreate(icicle);
4: setContentView(R.layout.preferences);
5:
6: TextView myTextVIew = (TextView)findViewById(R.id.myTextView);
7:
8: String text = "";
9: if(icicle != null && icicle.containsKey(TEXTVIEW_STATIC_KEY));
10: text = icicle.getString(TEXTVIEW_STATIC_KEY);
11:
12: myTextVIew.setText(text);
13:
14: }
⑵ 保存To-Do List活动状态
To-Do List(待办事项表)状态由三种变量组成:
·是否添加了新的条目
·新条目的输入文本框中存储了哪些文本?
·当前选择的条目是什么?
a.首先:添加静态字符串变量作为preference键
1: // UI State Key Constants
2: static final private String TEXT_ENTRY_KEY = "TEXT_ENTRY_KEY";
3: static final private String ADDING_ITEM_KEY = "ADDING_ITEM_KEY";
4: static final private String SELECTED_INDEX_KEY = "SELECTED_INDEX_KEY";
b.重写onPause方法,取得私有共享preference的Editor对象
然后用第1步的键存储所列的实例值
1: @Override
2: protected void onPause(){
3: super.onPause();
4:
5: // Get the activity preferences object.
6: SharedPreferences uiState = getPreferences(0);
7: // Get the preferences editor.
8: SharedPreferences.Editor editor = uiState.edit();
9:
10: // Add the UI state preference values.
11: editor.putString(TEXT_ENTRY_KEY, myEditText.getText().toString());
12: editor.putBoolean(ADDING_ITEM_KEY, addingNew);
13:
14: // Commit the preferences.
15: editor.commit();
16: }
⑶ 编写retoreUIState方法
1: @Override
2: public void onCreate(Bundle icicle) {
3: super.onCreate(icicle);
4: ...
5: restoreUIState();
6: }
7:
8: /** Apply the saved UI state */
9: private void restoreUIState() {
10: // Get the activity preferences object.
11: SharedPreferences settings = getPreferences(0);
12:
13: // Read the UI state values, specifying default values.
14: String text = settings.getString(TEXT_ENTRY_KEY, "");
15: Boolean adding = settings.getBoolean(ADDING_ITEM_KEY, false);
16:
17: // Restore the UI to the previous state.
18: if (adding) {
19: addNewItem();
20: myEditText.setText(text);
21: }
22: }
⑷ 使用OnSaveInstanceState/onRestoreInstanceState记录选中条目的索引
1: @Override
2: public void onSaveInstanceState(Bundle savedInstanceState) {
3: savedInstanceState.putInt(SELECTED_INDEX_KEY, myListView.getSelectedItemPosition());
4:
5: super.onSaveInstanceState(savedInstanceState);
6: }
7:
8: @Override
9: public void onRestoreInstanceState(Bundle savedInstanceState) {
10: int pos = -1;
11:
12: if (savedInstanceState != null)
13: if (savedInstanceState.containsKey(SELECTED_INDEX_KEY))
14: pos = savedInstanceState.getInt(SELECTED_INDEX_KEY, -1);
15:
16: myListView.setSelection(pos);
17: }
18:
4、为地震查看器创建一个preference页
(1)添加字符串资源,为显示的标签添加新的字符串资源
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Earthquake</string>
<string name="quake_feed">http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml</string>
<string name="menu_update">Refresh Earthquakes</string>
<string name="auto_update_prompt">Auto Update?</string>
<string name="update_freq_prompt">Update Frequency</string>
<string name="min_quake_mag_prompt">Minimum Quake Magnitude</string>
<string name="menu_preferences">Preferences</string>
</resources>
(2)创建新的preferences.xml,布局preferences活动的UI

preferences.xml
(3)在res/values/arrays.xml文件中创建4个数组

arrays.xml
(4) 创建preferenceit活动
重写onCreate,重写第2步的布局,获得复选框和spinner控件的引用,然后调用
populateSpinners存根
1: public class Preferences extends Activity {
2:
3: CheckBox autoUpdate;
4: Spinner updateFreqSpinner;
5: Spinner magnitudeSpinner;
6:
7: @Override
8: public void onCreate(Bundle icicle) {
9: super.onCreate(icicle);
10: setContentView(R.layout.preferences);
11:
12: updateFreqSpinner = (Spinner)findViewById(R.id.spinner_update_freq);
13: magnitudeSpinner = (Spinner)findViewById(R.id.spinner_quake_mag);
14: autoUpdate = (CheckBox)findViewById(R.id.checkbox_auto_update);
15:
16: populateSpinners();
17: }
18:
19: private void populateSpinners() { }
20: }
(5)用Array Adaper绑定spinner,完成populateSpinners():
1: private void populateSpinners() {
2: // 填充更新频率
3: ArrayAdapter<CharSequence> fAdapter;
4: fAdapter = ArrayAdapter.createFromResource(this, R.array.update_freq_options,
5: android.R.layout.simple_spinner_item);
6: fAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
7: updateFreqSpinner.setAdapter(fAdapter);
8:
9: // 填充最小震级
10: ArrayAdapter<CharSequence> mAdapter;
11: mAdapter = ArrayAdapter.createFromResource(this, R.array.magnitude_options,
12: android.R.layout.simple_spinner_item);
13: mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
14: magnitudeSpinner.setAdapter(mAdapter);
15: }
(6)创建命名的共享preference,更新onCreate进行检索preference,调用updateUIFromPreferences方法通过对共享的preference使用get<type>检索第一个preference值
1: SharedPreferences prefs;
2:
3: public static final String USER_PREFERENCE = "USER_PREFERENCES";
4:
5: public static final String PREF_AUTO_UPDATE = "PREF_AUTO_UPDATE";
6: public static final String PREF_MIN_MAG = "PREF_MIN_MAG";
7: public static final String PREF_UPDATE_FREQ = "PREF_UPDATE_FREQ";
8:
9: @Override
10: public void onCreate(Bundle icicle) {
11: super.onCreate(icicle);
12: setContentView(R.layout.preferences);
13:
14: updateFreqSpinner = (Spinner)findViewById(R.id.spinner_update_freq);
15: magnitudeSpinner = (Spinner)findViewById(R.id.spinner_quake_mag);
16: autoUpdate = (CheckBox)findViewById(R.id.checkbox_auto_update);
17:
18: populateSpinners();
19:
20: prefs = getSharedPreferences(USER_PREFERENCE, Activity.MODE_PRIVATE);
21: updateUIFromPreferences();
22: }
1: private void updateUIFromPreferences() {
2: boolean autoUpChecked = prefs.getBoolean(PREF_AUTO_UPDATE, false);
3: int updateFreqIndex = prefs.getInt(PREF_UPDATE_FREQ, 2);
4: int minMagIndex = prefs.getInt(PREF_MIN_MAG, 0);
5:
6: updateFreqSpinner.setSelection(updateFreqIndex);
7: magnitudeSpinner.setSelection(minMagIndex);
8: autoUpdate.setChecked(autoUpChecked);
9: }
1: @Override
2: public void onCreate(Bundle icicle) {
3: super.onCreate(icicle);
4: setContentView(R.layout.preferences);
5:
6: updateFreqSpinner = (Spinner)findViewById(R.id.spinner_update_freq);
7: magnitudeSpinner = (Spinner)findViewById(R.id.spinner_quake_mag);
8: autoUpdate = (CheckBox)findViewById(R.id.checkbox_auto_update);
9:
10: ....................
11:
12: Button okButton = (Button) findViewById(R.id.okButton);
13: okButton.setOnClickListener(new View.OnClickListener() {
14: public void onClick(View view) {
15: savePreferences();
16: Preferences.this.setResult(RESULT_OK);
17: finish();
18: }
19: });
20:
21: Button cancelButton = (Button) findViewById(R.id.cancelButton);
22: cancelButton.setOnClickListener(new View.OnClickListener() {
23: public void onClick(View view) {
24: Preferences.this.setResult(RESULT_CANCELED);
25: finish();
26: }
27: });
28: }
1: private void savePreferences() {
2: int updateIndex = updateFreqSpinner.getSelectedItemPosition();
3: int minMagIndex = magnitudeSpinner.getSelectedItemPosition();
4: boolean autoUpdateChecked = autoUpdate.isChecked();
5:
6: Editor editor = prefs.edit();
7: editor.putBoolean(PREF_AUTO_UPDATE, autoUpdateChecked);
8: editor.putInt(PREF_UPDATE_FREQ, updateIndex);
9: editor.putInt(PREF_MIN_MAG, minMagIndex);
10: editor.commit();
11: }
<activity android:name=".Preferences" android:label="Earthquake Preferences"></activity>
1: @Override
2: public boolean onCreateOptionsMenu(Menu menu) {
3: super.onCreateOptionsMenu(menu);
4:
5: menu.add(0, MENU_UPDATE, Menu.NONE, R.string.menu_update);
6: menu.add(0, MENU_PREFERENCES, Menu.NONE, R.string.menu_preferences);
7:
8: return true;
9: }
1: @Override
2: public boolean onOptionsItemSelected(MenuItem item) {
3: super.onOptionsItemSelected(item);
4:
5: switch (item.getItemId()) {
6: case (MENU_UPDATE): {
7: refreshEarthquakes();
8: return true;
9: }
10: case (MENU_PREFERENCES): {
11: Intent i = new Intent(this, Preferences.class);
12: startActivityForResult(i, SHOW_PREFERENCES);
13: return true;
14: }
15: }
16: return false;
17: }
(12)启动程序,从菜单中选择Preference
(13)把Preference应用到Earthquake功能中,以上的应用框架已经搭好。
(14)创建updateFromPreferences读取共享Preference,为第一个值创建实例变量
1: private void updateFromPreferences() {
2: SharedPreferences prefs = getSharedPreferences(Preferences.USER_PREFERENCE, Activity.MODE_PRIVATE);
3:
4: int minMagIndex = prefs.getInt(Preferences.PREF_MIN_MAG, 0);
5: if (minMagIndex < 0)
6: minMagIndex = 0;
7:
8: int freqIndex = prefs.getInt(Preferences.PREF_UPDATE_FREQ, 0);
9: if (freqIndex < 0)
10: freqIndex = 0;
11:
12: autoUpdate = prefs.getBoolean(Preferences.PREF_AUTO_UPDATE, false);
13:
14: Resources r = getResources();
15: // Get the option values from the arrays.
16: int[] minMagValues = r.getIntArray(R.array.magnitude);
17: int[] freqValues = r.getIntArray(R.array.update_freq_values);
18:
19: // Convert the values to ints.
20: minimumMagnitude = minMagValues[minMagIndex];
21: updateFreq = freqValues[freqIndex];
22: }
(15)更新addNewQuake方法,用地震过滤器来检查一个新的地震震级,然后将其添加到列表中
1: private void addNewQuake(Quake _quake) {
2: if(_quake.getMagnitude()>minimumMagnitude)
3: //向我们的地震列表添加新的地震
4: earthquakes.add(_quake);
5:
6: // 把这个改变通知ArrayAdapter
7: aa.notifyDataSetChanged();
8: }
(16) 重写onActivityResult调用updateFormPreference,在保存了修改后刷新地震
1: @Override
2: public void onActivityResult(int requestCode, int resultCode, Intent data) {
3: super.onActivityResult(requestCode, resultCode, data);
4:
5: if (requestCode == SHOW_PREFERENCES)
6: if (resultCode == Activity.RESULT_OK) {
7: updateFromPreferences();
8: refreshEarthquakes();
9: }
10: }
1: @Override
2: public void onCreate(Bundle icicle) {
3: super.onCreate(icicle);
4: setContentView(R.layout.main);
5:
6: earthquakeListView = (ListView)this.findViewById(R.id.earthquakeListView);
7: earthquakeListView.setOnItemClickListener(new OnItemClickListener() {
8: public void onItemClick(AdapterView<?> _av, View _v, int _index, long _id) {
9: selectedQuake = earthquakes.get(_index);
10: showDialog(QUAKE_DIALOG);
11: }
12: });
13:
14: aa = new ArrayAdapter<Quake>(getApplicationContext(), android.R.layout.simple_list_item_1, earthquakes);
15: earthquakeListView.setAdapter(aa);
16:
17: loadQuakesFromProvider();
18:
19: updateFromPreferences();
20: refreshEarthquakes();
21: }
(17)在onCreate中调用updateFormPreference,在活动第一次启动时preference被应用
1: @Override
2: public void onCreate(Bundle icicle) {
3: super.onCreate(icicle);
4: setContentView(R.layout.main);
5:
6: earthquakeListView = (ListView)this.findViewById(R.id.earthquakeListView);
7: earthquakeListView.setOnItemClickListener(new OnItemClickListener() {
8: public void onItemClick(AdapterView<?> _av, View _v, int _index, long _id) {
9: selectedQuake = earthquakes.get(_index);
10: showDialog(QUAKE_DIALOG);
11: }
12: });
13:
14: aa = new ArrayAdapter<Quake>(getApplicationContext(), android.R.layout.simple_list_item_1, earthquakes);
15: earthquakeListView.setAdapter(aa);
16:
17: loadQuakesFromProvider();
18:
19: updateFromPreferences();
20: refreshEarthquakes();
21: }