我的Android 4 学习系列之文件、保存状态和首选项

目录
  • 使用Shared Preference 保留简单的应用程序数据

  • 保存回话间的Activity实例数据
  • 管理应用程序首选项和创建Preference Screen
  • 保存并加载文件以及管理本地文件系统
  • 将静态文件作为外部资源添加
使用Shared Preference 保留简单的应用程序数据

Shared Prefrence 是一种简单的、轻量级的名/值对(NVP)机制,用于保存原始应用程序数据,最常见的是用户的应用程序首选项。

Android 中的数据持久化技术为平衡速度、效率和健壮性提供了选项。

  • Shared Preference 当存储UI状态、用户首选项或者应用程序设置时,Shared Preference 使我们能够将一组原始数据的名/值对保存为命名的首选项(Named Preference)。

  • 已保存的应用程序UI状态 当应用程序移动到后台时,Activity和Fragment会包含专用的事件处理程序以记录当前的UI状态
  • 文件 虽然这种方式并不完美,但有时从文件中写入和读取数据是解决问题的唯一途径。Android 使我们能够在设备的内部或者外部媒体上创建并加载文件。它为临时缓冲提供支持,并将文件存储到公共的可访问的文件夹中。
保存会话间的Activity实例数据

使用SharedPreference类可以创建名称/值对的命名映射,它们可以在会话之间持久化,并在同一个应用程序沙箱中运行的应用程序组件之间共享。

  1: SharedPreferences sp = getSharedPreferences("MY_SP", Activity.MODE_PRIVATE);
 修改Shared Preference,使用put<Type>方法来插入或更新与指定名称关联的值。
  1: SharedPreferences.Editor editor = sp.edit();
  2: editor.putBoolean("isTrue", true);
  3: editor.putFloat("lastFloat", 0.1f);

要保存编辑动作,只需要调用Editor对象apply或者commit来分别异步或者同步地保存更改。

  1: editor.apply();
 检索 Shared Preference
  1: boolean isTrue = sp.getBoolean("isTrue", false);
  2: float lastFloat = sp.getFloat("lastFloat", 0f);
 所有可用的键值引用和某个键值是否存在
  1: Map<String, ?> allPreferences = sp.getAll();
  2: boolean contains = sp.contains("isTrue");
 为地震查看器创建一个设置Activity, 继续前一篇中Demo Earthquake。
(1)打开Earthquake 项目,首先添加字符串资源。
  1: <?xml version="1.0" encoding="utf-8"?>
  2: <resources>
  3:   <string name="app_name">Earthquake</string>
  4:   <string name="quake_feed">
  5:     http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml
  6:   </string>
  7:   <string name="menu_update">Refresh Earthquake</string>
  8:   <string name="auto_update_prompt">Auto Update?</string>
  9:   <string name="update_freq_prompt">Update Frequency</string>
 10:   <string name="min_quake_mag_prompt">Minmum Quake Magnitude</string>
 11:   <string name="menu_preferences">Preferences</string>
 12:   <string name="ok">OK</string>
 13:   <string name="cancel">Cancel</string>
 14: </resources>

(2)在res/loyout文件夹中,为Preference Activity 创建一个新的preferences.xml布局资源。包含一个复选框用于指示自动更新是否打开,还有两个微调框用于选择更新速率和震级过滤器:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3:     android:layout_width="fill_parent"
  4:     android:layout_height="fill_parent"
  5:     android:orientation="vertical">
  6:
  7:     <TextView
  8:         android:layout_width="fill_parent"
  9:         android:layout_height="wrap_content"
 10:         android:text="@string/auto_update_prompt" />
 11:
 12:     <CheckBox android:id="@+id/checkbox_auto_update"
 13:         android:layout_width="fill_parent"
 14:         android:layout_height="wrap_content" />
 15:
 16:     <TextView
 17:         android:layout_width="fill_parent"
 18:         android:layout_height="wrap_content"
 19:         android:text="@string/update_freq_prompt" />
 20:
 21:     <Spinner android:id="@+id/spinner_update_freq"
 22:         android:layout_width="fill_parent"
 23:         android:layout_height="wrap_content"
 24:         android:drawSelectorOnTop="true" />
 25:
 26:     <TextView
 27:         android:layout_width="fill_parent"
 28:         android:layout_height="wrap_content"
 29:         android:text="@string/min_quake_mag_prompt" />
 30:
 31:     <Spinner android:id="@+id/spinner_quake_mag"
 32:         android:layout_width="fill_parent"
 33:         android:layout_height="wrap_content"
 34:         android:drawSelectorOnTop="true" />
 35:
 36:     <LinearLayout
 37:         android:orientation="horizontal"
 38:         android:layout_width="fill_parent"
 39:         android:layout_height="wrap_content">
 40:
 41:         <Button android:id="@+id/okButton"
 42:             android:layout_width="wrap_content"
 43:             android:layout_height="wrap_content"
 44:             android:text="@string/ok" />
 45:
 46:         <Button android:id="@+id/cancelButton"
 47:             android:layout_width="wrap_content"
 48:             android:layout_height="wrap_content"
 49:             android:text="@string/cancel" />
 50:
 51:     </LinearLayout>
 52:
 53: </LinearLayout>
 54: 

(3)创建一个新的res/values/arrays.xml 文件创建4个数组资源。他们将为更新频率和最小震级微调框提供所用值:

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <resources>
  3:     <string-array name="update_freq_options">
  4:         <item >Every Minute</item>
  5:         <item >5 minutes</item>
  6:         <item >10 minutes</item>
  7:         <item >15 minutes</item>
  8:         <item >Every Hour</item>
  9:     </string-array>
 10:     <string-array name="magnitude">
 11:         <item >3</item>
 12:         <item >5</item>
 13:         <item >6</item>
 14:         <item >7</item>
 15:         <item >8</item>
 16:     </string-array>
 17:     <string-array name="magnitude_options">
 18:         <item >3</item>
 19:         <item >5</item>
 20:         <item >6</item>
 21:         <item >7</item>
 22:         <item >8</item>
 23:     </string-array>
 24:     <string-array name="update_freq_values">
 25:         <item >1</item>
 26:         <item >5</item>
 27:         <item >10</item>
 28:         <item >15</item>
 29:         <item >60</item>
 30:     </string-array>
 31: </resources>
 32: 

(4)创建 PreferenceActivity Activity。重写onCreate 以填充我们在第(2)步创建的布局资源,然后获取微调框的控件的引用,之后调用populateSpinner stub:

  1: package com.paad.earthquake;
  2:
  3: import android.app.Activity;
  4: import android.content.Context;
  5: import android.content.SharedPreferences;
  6: import android.content.SharedPreferences.Editor;
  7: import android.os.Bundle;
  8: import android.preference.PreferenceManager;
  9: import android.view.View;
 10: import android.widget.ArrayAdapter;
 11: import android.widget.Button;
 12: import android.widget.CheckBox;
 13: import android.widget.Spinner;
 14:
 15: public class PreferencesActivity extends Activity {
 16:
 17:   CheckBox autoUpdate;
 18:   Spinner updateFreqSpinner;
 19:   Spinner magnitudeSpinner;
 20:
 21:   @Override
 22:   public void onCreate(Bundle savedInstanceState){
 23:     super.onCreate(savedInstanceState);
 24:     setContentView(R.layout.preferences);
 25:
 26:     updateFreqSpinner = (Spinner)findViewById(R.id.spinner_update_freq);
 27:     magnitudeSpinner = (Spinner)findViewById(R.id.spinner_quake_mag);
 28:     autoUpdate = (CheckBox)findViewById(R.id.checkbox_auto_update);
 29:
 30:     populateSpinners();
 31:   }
 32:
 33:   private void populateSpinners() {
 34:   }
 35: }
 36: 

(5) 完成 populateSpinner 方法, 使用Array Adapter(数组适配器)将每个微调框都绑定到与其相应的数组:

  1: private void populateSpinners() {
  2:     // 填充更新频率微调框
  3:     ArrayAdapter<CharSequence> fAdapter;
  4:     fAdapter = ArrayAdapter.createFromResource(this, R.array.update_freq_options, android.R.layout.simple_spinner_item);
  5:     int spinner_dd_item = android.R.layout.simple_spinner_dropdown_item;
  6:     fAdapter.setDropDownViewResource(spinner_dd_item);
  7:     updateFreqSpinner.setAdapter(fAdapter);
  8:
  9:     //填充最小震级微调区
 10:     ArrayAdapter<CharSequence> mAdapter;
 11:     mAdapter = ArrayAdapter.createFromResource(this, R.array.magnitude_options, android.R.layout.simple_selectable_list_item);
 12:     mAdapter.setDropDownViewResource(spinner_dd_item);
 13:     magnitudeSpinner.setAdapter(mAdapter);
 14:   }

(6)添加公共静态字符串值, 用于标识用来存储每个首选项值的Shared Preference键。更新onCreate

  1: package com.paad.earthquake;
  2:
  3: import android.app.Activity;
  4: import android.content.Context;
  5: import android.content.SharedPreferences;
  6: import android.content.SharedPreferences.Editor;
  7: import android.os.Bundle;
  8: import android.preference.PreferenceManager;
  9: import android.view.View;
 10: import android.widget.ArrayAdapter;
 11: import android.widget.Button;
 12: import android.widget.CheckBox;
 13: import android.widget.Spinner;
 14:
 15: public class PreferencesActivity extends Activity {
 16:
 17:   public static final String USER_PREFERENCES = "USER_PREFERENCES";
 18:   public static final String PREF_AUTO_UPDATE = "PREF_AUTO_UPDATE";
 19:   public static final String PREF_MIN_MAG_INDEX = "PREF_MIN_MAG_INDEX";
 20:   public static final String PREF_UPDATE_FREQ_INDEX = "PREF_UPDATE_FREQ_INDEX";
 21:
 22:   SharedPreferences prefs;
 23:
 24:   CheckBox autoUpdate;
 25:   Spinner updateFreqSpinner;
 26:   Spinner magnitudeSpinner;
 27:
 28:   @Override
 29:   public void onCreate(Bundle savedInstanceState){
 30:     super.onCreate(savedInstanceState);
 31:     setContentView(R.layout.preferences);
 32:
 33:     updateFreqSpinner = (Spinner)findViewById(R.id.spinner_update_freq);
 34:     magnitudeSpinner = (Spinner)findViewById(R.id.spinner_quake_mag);
 35:     autoUpdate = (CheckBox)findViewById(R.id.checkbox_auto_update);
 36:
 37:     populateSpinners();
 38:
 39:     Context context = getApplicationContext();
 40:     prefs = PreferenceManager.getDefaultSharedPreferences(context);
 41:
 42:     updateUIFormPreferences();
 43:   }
 44:
 45:   private void updateUIFormPreferences() {
 46:     boolean autoUpChecked = prefs.getBoolean(PREF_AUTO_UPDATE, false);
 47:     int updateFreqIndex = prefs.getInt(PREF_UPDATE_FREQ_INDEX, 2);
 48:     int minMagIndex = prefs.getInt(PREF_MIN_MAG_INDEX, 0);
 49:     updateFreqSpinner.setSelection(updateFreqIndex);
 50:     magnitudeSpinner.setSelection(minMagIndex);
 51:     autoUpdate.setChecked(autoUpChecked);
 52:   }
 53: }
 54: 

(7)仍然是在 onCreate 方法中, 为OK 和 Cancel 按钮添加事件处理程序。

  1:     Button okButton = (Button)findViewById(R.id.okButton);
  2:     okButton.setOnClickListener(new View.OnClickListener() {
  3:
  4:       @Override
  5:       public void onClick(View v) {
  6:         savePreference();
  7:         PreferencesActivity.this.setResult(RESULT_OK);
  8:         finish();
  9:       }
 10:
 11:       private void savePreference() {
 12:         int updateIndex = updateFreqSpinner.getSelectedItemPosition();
 13:         int minMagIndex = magnitudeSpinner.getSelectedItemPosition();
 14:         boolean autoUpdateChecked = autoUpdate.isChecked();
 15:
 16:         Editor editor = prefs.edit();
 17:         editor.putBoolean(PREF_AUTO_UPDATE, autoUpdateChecked);
 18:         editor.putInt(PREF_UPDATE_FREQ_INDEX, updateIndex);
 19:         editor.putInt(PREF_MIN_MAG_INDEX, minMagIndex);
 20:         editor.commit();
 21:       }
 22:     });
 23:
 24:     Button cancelButton = (Button)findViewById(R.id.cancelButton);
 25:     cancelButton.setOnClickListener(new View.OnClickListener() {
 26:
 27:       @Override
 28:       public void onClick(View v) {
 29:         PreferencesActivity.this.setResult(RESULT_CANCELED);
 30:         finish();
 31:       }
 32:     });

(8)mainifest中加入Preferences Activity:

  1:     <activity android:name=".PreferencesActivity"
  2:         android:label="Earthquake Preferences">
  3:
  4:     </activity>

(9)返回到Earthquake Activity中,并为新的Shared Preference 文件和菜单添加支持以显示该Preferences Activity:

  1: package com.paad.earthquake;
  2: 
  3: import android.app.Activity;
  4: import android.content.Intent;
  5: import android.os.Bundle;
  6: import android.view.Menu;
  7: import android.view.MenuItem;
  8: 
  9: public class Earthquake extends Activity {
 10:     private static final int MENU_PREFERENCES = Menu.FIRST + 1;
 11:     private static final int MENU_UPDATE = Menu.FIRST + 2;
 12:     
 13:     private int SHOW_PREFERENCES = 1;
 14:   
 15:     @Override
 16:     public void onCreate(Bundle savedInstanceState) {
 17:         super.onCreate(savedInstanceState);
 18:         setContentView(R.layout.main);
 19:     }
 20:     
 21:     @Override
 22:     public boolean onCreateOptionsMenu(Menu menu){
 23:     super.onCreateOptionsMenu(menu);
 24:     
 25:     menu.add(0, MENU_PREFERENCES, Menu.NONE, R.string.menu_preferences);
 26:       
 27:       return true;      
 28:     }
 29:     
 30:     @Override
 31:     public boolean onOptionsItemSelected(MenuItem item){
 32:     super.onOptionsItemSelected(item);
 33:     
 34:     switch(item.getItemId()){
 35:       case (MENU_PREFERENCES) : {
 36:         Intent i = new Intent(this, PreferencesActivity.class);
 37:         startActivityForResult(i, SHOW_PREFERENCES);
 38:         return true;
 39:       }
 40:     }
 41:       
 42:       return false;      
 43:     }
 44: }

(10)启动应用程序并从Activity的菜单中选择Preferences。

(11)现在剩余的工作就是就是将首选项应用到地震功能中。如何实现自动更新功能放到后面下下一篇学习使用Service和后台线程。

现在我们能够将框架准备就绪并应用震级过滤器。首先在Earthquake Activity中创建方法updateFromPreferences,用于读取SharedPreference值。

  1:   public int minimumMagnitude = 0;
  2:   public boolean autoUpdateChecked = false;
  3:   public int updateFreq = 0;
  4:
  5:   private void updateFromPreference(){
  6:     Context context = getApplicationContext();
  7:     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  8:
  9:     int minMagIndex = prefs.getInt(PreferencesActivity.PREF_MIN_MAG_INDEX, 0);
 10:     if(minMagIndex < 0) minMagIndex = 0;
 11:
 12:     int freqIndex = prefs.getInt(PreferencesActivity.PREF_UPDATE_FREQ_INDEX, 0);
 13:     if(freqIndex < 0) freqIndex = 0;
 14:
 15:     autoUpdateChecked = prefs.getBoolean(PreferencesActivity.PREF_AUTO_UPDATE, false);
 16:
 17:     Resources r = getResources();
 18:     //从数组中获取选项值
 19:     String[] minMagValues = r.getStringArray(R.array.magnitude);
 20:     String[] freqValues = r.getStringArray(R.array.update_freq_values);
 21:
 22:     //将值转换成整型
 23:     minimumMagnitude = Integer.valueOf(minMagValues[minMagIndex]);
 24:     updateFreq = Integer.valueOf(freqValues[freqIndex]);
 25:   }

(12) 更新EarthquakeListFragment的addNewQuake方法应用震级过滤器

  1: private void addNewQuake(Quake _quake) {
  2:     // Add the new quake to our list of earthquakes.
  3:   Earthquake earthquakeActivity = (Earthquake)getActivity();
  4:   if(_quake.getMagnitude() > earthquakeActivity.minimumMagnitude){
  5:     earthquakes.add(_quake);
  6:   }
  7:
  8:     // Notify the array adapter of a change.
  9:     aa.notifyDataSetChanged();
 10:   }
 11: 

(13) 返回到Earthquake Activity,重写onActivityResult处理程序以调用updateFromPreferences,并且每当Preferences Activity 保存之后就刷新地震信息。

  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:           updateFromPreference();
  8:           FragmentManager fm = getFragmentManager();
  9:           final EarthquakeListFragment earthquakeList = (EarthquakeListFragment)fm.findFragmentById(R.id.EarthquakeListFragment);
 10:
 11:           Thread t = new Thread(new Runnable(){
 12:
 13:           @Override
 14:           public void run() {
 15:             earthquakeList.refreshEarthquakes();
 16:           }
 17:
 18:           });
 19:
 20:           t.start();
 21:         }
 22:       }
 23:     }

(14)最后,在Earthquake Activity的onCreate方法中调用updateFromPreferences,以确保当Activity启动时首选项应该被应用。

  1: @Override
  2:     public void onCreate(Bundle savedInstanceState) {
  3:         super.onCreate(savedInstanceState);
  4:         setContentView(R.layout.main);
  5:
  6:         updateFromPreference();
  7:     }

管理应用程序首选项和创建Preference Screen

Android 提供了一个XML驱动的框架,用于为应用程序创建系统样式的Preference Screen。通过使用该框架,能够确保应用程序中的Preference Activity与本地和其他第三方应用程序所使用的一致。

Preference Activity 框架由4个部分组成:

  • Preference Screen 布局 一个XML文件,定义了在Preference Screen 中显示的层次结构。它指定了要显示的文本及相关控件、所允许的值和每个控件使用的Shared Preference键。

  • Preference Activity 和 Preference Fragment 分别是PreferenceActivity和PreferenceFragment的扩展,用于包含Preference Screen
  • Preference Header 定义 一个XML文件,定义了应用程序的Preference Fragment,以及用于显示Preference Fragment的层次结构。
  • Shared Preferences 变化监听程序 一个onSharedPreferenceChangeListener 类的实现, 用于监听Shared Preference 的变化

与标准UI布局不同,首选项定义存储在res/xml资源文件夹中。

Preference 使用了专门为首选项设计的控件集

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
  3:
  4:
  5: </PreferenceScreen>

可以包含额外的Preference Screen元素,每一个将被表示为一个可选择的元素,单击他们将会显示出一个新的屏幕。

在每个Preference Screen内部可包含PreferenceCategory 和 Preference<control> 元素的任意组合

  1: <CheckBoxPreference
  2:       android:key="PREF_CHECK_BOX"
  3:       android:title="Check Box Preference"
  4:       android:summary="Cheeck Box Preference Description"
  5:       android:defaultValue="true" />

1. 原生的首选项控件

  • CheckBoxPreference

  • EditTextPreference
  • ListPreference
  • MultiSelectListPreference
  • RingtonePreference

2. 使用Intent在Preference Screen中导入系统首选项

可以使用一个Intent调用自己的Preference Screen 中的任何 Activity。如果在一个Preference Screen元素中添加一个Intent节点,那么系统会将该操作理解为使用指定动作请求调用startActivity。

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
  3:
  4:     <Intent android:action="android.setting.DISPLAY_SETTINGS"></Intent>
  5:
  6: </PreferenceScreen>
  7: 

android.provider.Settings 类包含了大量的 android.settings.* 常量,他们能够用于调用系统设置屏幕。

manifest中的注册:

  1: <activity android:name=".PreferencesActivity" android:label="Earthquake Preferences">
  2:     <intent-filter>
  3:        <action android:name="com.paad.myapp.ACTION_USER_PREFERENCE" />
  4:     </intent-filter>
  5: </activity>

Preference Fragment

  1: package com.paad.earthquake;
  2:
  3: import android.annotation.SuppressLint;
  4: import android.os.Bundle;
  5: import android.preference.PreferenceFragment;
  6:
  7: @SuppressLint("NewApi")
  8: public class MyPreferenceFragment extends PreferenceFragment {
  9:
 10:   @Override
 11:   public void onCreate(Bundle savedInstanceState){
 12:     super.onCreate(savedInstanceState);
 13:     addPreferencesFromResource(R.xml.preference_screen_test);
 14:   }
 15: }
 16: 

使用Preference Header 定义 Preference Fragment的层次结构

preference Header 是一些XML资源, 描述了Preference Fragment 在Preference Activity中如何分组和显示,每个头都标识并选择一个特定的Preference Fragment。当选中该头时,Fragment就会显示出来

Preference Activity

PreferenceActivity 类用于包含PreferenceHeader资源定义的Preference Fragment层次结构。

为了创建一个新的Preference Activity,扩展PreferenceActivity类,如下:

  1: package com.paad.earthquake;
  2:
  3: import java.util.List;
  4:
  5: import android.annotation.SuppressLint;
  6: import android.preference.PreferenceActivity;
  7:
  8: @SuppressLint("NewApi")
  9: public class MyPreferenceActivity extends PreferenceActivity {
 10:
 11: }

使用Preference Fragment 和 Preference Header 时,需要重写onBuildHeaders 处理程序,在其中调用的 loadHeaddersFromResource(R.xml.userpreferenceheaders, target)

  1: @SuppressLint("NewApi")
  2: public class MyPreferenceActivity extends PreferenceActivity {
  3:
  4:   @Override
  5:   public void onBuildHeaders(List<Header> target) {
  6:         loadHeadersFromResource(R.xml.my_preference_header, target);
  7:     }
  8: }

象所有Activity一样,都需要在manifest中进行注册

  1:     <activity android:name=".MyPreferenceActivity" android:label="My Preferences">
  2:
  3:     </activity>

为了显示在该Activity中包含的应用程序设置,需要调用startActivity或者starteActivityForResult打他开它:

  1: Intent i = new Intent(this, MyPreferenceActivity.class);
  2: startActivityForResult(i, SHOW_PREFERENCES);

向后兼容性与Preference Screen

Android 3.0 (API Level 11)之前的Android平台是不支持 Preference Fragment 及 Prenference Header的。因此,如果想让应用程序同时运行在早于和晚于Honeycomb版本的设备,就需要分别实现Preference Activity来支持这两种设备,并在运行时启动合适的Activity

  1:         Class c = Build.VERSION.SDK_INT<Build.VERSION_CODES.HONEYCOMB ? MyPreferenceActivity.class : MyFragmentPreferenceActivity.class;
  2:
  3:         Intent i = new Intent(this, c);
  4:         startActivityForResult(i, SHOW_PREFERENCES);

找到并使用Preference Screen 设置 Shared Preference

为Preference Activity中的选项记录的Shared Preference值被存储在应用程序的沙箱中。这使得任何应用程序组件,包括Activity、Service和Broadcast Receiver都能访问该值:

Context context = getApplicationContext();

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

Shared Preference Change Listener 简介

可以实现 onSharedPreferenceChangeListener, 每当添加,移除或者修改一个特定的Shared Preference时来调用一个回调函数。

现在为地震查看器创建一个标准的Preference Activity

(1)首先在res/xml下创建一个新的XML资源文件夹。在其中创建userpreferences.xml.

  1: <?xml version="1.0" encoding="utf-8"?>
  2: <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
  3:
  4:     <CheckBoxPreference
  5:         android:key="PREF_AUTO_UPDATE"
  6:         android:title="Atuo refresh"
  7:         android:summary="Select to turn on automatic updating"
  8:         android:defaultValue="true" />
  9:
 10:     <ListPreference
 11:         android:key="PREF_UPDATE_FREQ"
 12:         android:title="Refresh frequency"
 13:         android:summary="Frequency at which to refresh earthquake list"
 14:         android:entries="@array/update_freq_options"
 15:         android:entryValues="@array/update_freq_values"
 16:         android:dialogTitle="Refresh frequency"
 17:         android:defaultValue="60" />
 18:
 19:     <ListPreference
 20:         android:key="PREF_MIN_MAG"
 21:         android:title="Minimum Magnitude"
 22:         android:summary="Select the minimum magnitude earthquake to report"
 23:         android:entries="@array/magnitude_options"
 24:         android:entryValues="@array/magnitude"
 25:         android:dialogTitle="Magnitude"
 26:         android:defaultValue="3" />
 27:
 28: </PreferenceScreen>
 29: 

(2) 打开Prefrence Activity 将处理UI中用到的控件,移除对UI对象的引用,populateSprinners、updateUIFromPreferences和savePreferences 方法。

需要更新Preference名称字符串,以便和第(1)步中创建的userpreferences中使用的字符串匹配

  1:   public static final String PREF_MIN_MAG = "PREF_MIN_MAG";
  2:   public static final String PREF_UPDATE_FREQ = "PREF_UPDATE_FREQ";
  3:   public static final String PREF_AUTO_UPDATE = "PREF_AUTO_UPDATE";

(5) 打开Earthquake Activity 并更新updateFromPreferencesMethod。使用这种方法时,选中的值本身会存储在首选项中,所以没有必要执行数组查找。

private void updateFromPreference(){
    Context context = getApplicationContext();
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    //将值转换成整型
    minimumMagnitude = Integer.parseInt(prefs.getString(PreferencesActivity.PREF_MIN_MAG, "3"));
    updateFreq = Integer.parseInt(prefs.getString(PreferencesActivity.PREF_UPDATE_FREQ, "60"));
    autoUpdateChecked = prefs.getBoolean(PreferencesActivity.PREF_AUTO_UPDATE, false);
}

(6)更新onActionResult处理程序,删除返回值的检查。使用这种方法,所有对用户Preference更改立即生效。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data){
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == SHOW_PREFERENCES){
            updateFromPreference();
            FragmentManager fm = getFragmentManager();
            final EarthquakeListFragment earthquakeList = (EarthquakeListFragment)fm.findFragmentById(R.id.EarthquakeListFragment);
            Thread t = new Thread(new Runnable(){

@Override
                public void run() {
                    earthquakeList.refreshEarthquakes();
                }
            });
            t.start();
        }
    }

(7)效果运行:

持久化应用程序实例的状态

1. 使用Shared Preference 保存 Activity 状态

如果想要保存并不需要与其他组件共享的Activity信息,那么可以调用Activity.getPreference(), 而不需要制定一个Shared Preference名称。这会返回一个Shared Preference,其名称就是调用Activity的名称。

//创建和检索Activity首选项对象

SharedPreferences activityPreferences = getPreferences(Activity.MODE_PRIVATE);

//获得编辑器以修改Preference

SharedPreferences.Editor e = activityPreferences.edit();

//获得视图

TextView tv = (TextView)findViewById(R.id.myTextView);

//在Shared Preference对象中存储新的基本类型

e.putString(“currentTextValue”, tv.getText().toString());

e.apply();

2. 使用生命周期处理程序保存和还原Activity实例

Activity提供了onSaveInstanceState处理程序来持久化与会话之间的UI状态关联的数据。这是一个专门设计的处理程序,用于运行时终止Activity时保存UI状态。

通过重写一个Activity的onSaveInstanceState事件处理程序,可以使用它的Bundle参数来保存UI实例的值。在修改的Bundle参数传入超类的处理程序之前,使用与Shared Preference相同的put方法来存储值。

使用生命周期处理程序保存和还原Fragment实例状态

如果Activity被销毁,然后被重新启动,以处理硬件配置改变(如屏幕方向改变)的情况,那么可以请求保留Fragment状态。通过在Fragment的onCreate处理程序内调用setRemainInstance,就指定了当与Fragment关联的Actrivity被重新创建时,Fragment的实例不应该被终止和重新启动。

将静态文件作为外部资源添加

Resources r = getResources();

InputStream myFile = r.openRawResource(R.raw.myfilename);

在文件系统下工作

1. 文件管理工具

Android提供了一些基本的文件管理工具来帮助用户处理文件系统。这些实用工具都位于java.io.File 包中。

  • deleteFile

  • fileList 返回一个字符串数组,其中包含了由当前应用程序创建的所有文件。

2. 使用于特定应用程序的文件夹来存储文件:内部存储和外部存储。

Android 通过应用程序的上下文提供了两种相应的方法:getDir和getExternalFilesDir,两个方法都返回一个File对象,每个对象会包含有指向内部或者外部的应用程序文件存储目录的路径。

当应用程序卸载后,存储在这些目录或者子文件夹下的所有文件都将被删除。

3. 创建私有的应用程序文件

Android提供了openFileInput和openFileOutput方法来简化从应用程序沙箱中的文件读取数据流和向应用程序沙箱中的文件写入数据流的过程。

这些方法只支持当前的应用程序文件夹中的文件,指定路径分隔符将抛出异常。

4. 使用应用程序文件

如果应用程序需要缓冲临时文件,Android提供了一个可管理的内部缓冲和一个不可管理的外部缓存。分别调用getCacheDir 和 getExternalCacheDir 方法可以从当前的上下文中访问他们。

5. 存储公共可读文件

Evironment.getExternalStoragePublicDirectory。该方法接受一个字符串参数,该字符串参数通过使用一系列的Environment静态常量,确定要访问的子目录。

  • DIRECTORY_ALARMS
  • DIRECTORY_DCIM
  • DIRECTORY_DOWNLOADS
  • DIRECTORY_MOVIES
  • DIRECTORY_NOTIFICATIONS
  • DIRECTORY_PICTURES
  • DIRECTORY_PODCASTS
  • DIRECTORY_RINGTONES

这一张搞完唉。

时间: 2024-10-18 10:05:53

我的Android 4 学习系列之文件、保存状态和首选项的相关文章

Android开发 - 文件、保存状态和首选项

一个Activity至少应当在进入不活动状态前保存它的用户界面(UI)状态. Activity生命周期 创建并保存Shared Preference Shared Preference是一种简单的.轻量级的名称/值对(NVP)机制,用于保存原始应用程序数据. 使用SharedPreference类可以创建名称/值对的命名映射,它们可以在会话之间持久化,并在同一个应用程序沙箱中运行的应用程序组件之间共享(但是对其他应用程序不可用). 为了创建或者修改一个Shared Preference,可以调用

【Android】PA4D_CH7 文件、保存状态和首选项

本章主要知识点如下: 了解Shared Preferences 接口OnSharedPreferenceChangeListener, 每当添加.移除或者修改一个特定的Shared Preference 时候可以调用一个回调函数 创建Preference Screen(首选项框架) PreferenceActivity,  适用于API Level 11 (SDK3.0) 以前(xml 配置) PreferenceFragment, 适用于API Level 11 (SKD3.0) 以后,兼容平

我的Android 4 学习系列

Android 简介 开始入手 创建应用程序和Activity 创建用户界面 Intent 和 Broadcast Revicever 使用 Internet 资源 文件,保存状态和首选项 数据库和Content Provider 在后台操作 扩展用户体验 高级用户体验 硬件传感器 地图,地理编码和基于位置的服务 个性化主屏 音频.视频以及摄像头的使用 蓝牙.NFC.网络和Wi-Fi 电话服务和SMS Android 高级开发 推广和发布应用程序并从中获利 我的Android 4 学习系列

我的Android 4 学习系列之开始入手:配置开发环境与理解Hello World!

p { padding-left: 10px; } 目录 如何安装Android SDK.创建开发环境和调试项目 移动设计中一些注意事项 使用Android虚拟设备.模拟器和其他开发工具 如何安装Android SDK.创建开发环境和调试项目 下载和安装Android SDK : 我的是window7系统,当然下载 SDK starter package 最合适了: http://developer.android.com/sdk/index.html 下载完打开压缩包如下: 然后把这个包解压到

我的Android 4 学习系列之创建应用程序和Activity:Manifest、Application、Activity

目录 介绍Android应用程序组件,以及使用这些组件构建的各种Android应用程序 Android应用程序的生命周期 如何创建应用程序Manifest 如何使用外部资源提供对位置.语言和硬件配置的支持 如何实现和使用自己的Application类 如何创建新的Activity 理解Activity的状态转换和生命周期 Android应用程序的组成部分 Android应用程序是由松散耦合的组件构成的,并使用应用程序Manifest绑定到一起. Manifest描述了每一个组件以及他们之间的交互

我的Android 4 学习系列之创建用户基本界面

目录 使用视图和布局 理解Fragment 优化布局 创建分辨率无关的用户界面 扩展.分组.创建和使用视图 使用适配器将数据绑定到视图 使用视图和布局 1. Android UI 几个基本概念 视图: 所有可视界面的元素(通常称为控件或者小组件)的基类.所有的UI控件(包括布局类)都是由 View 派生而来的. 视图组:视图类的扩展,可以包含多个子视图.通过扩展ViewGroup类,可以创建由多个相互连接的子视图组成复合控件:还可以通过扩展ViewGroup类来提供布局管理器,以帮助在Aciti

Android 存储学习之使用SharedPreference保存文件

上两节我们都是使用文本文件保存用户的信息,这明显是存在漏洞的.同时对文件中的内容不好管理.今天我们学习用SharedPreference保存.sharedPreference是专门保存一些比较零散的数据的. 我们还是用上节的例子分析,将用户的信息使用SharedPreference来保存. 注意:如果不知道是什么例子,请看Android 存储学习之在内部存储中读写文件 当点击确定按钮后,就会保存用户的信息: public void login(View v) { String name = ed

我的Android 4 学习系列之使用 Internet 资源

目录 连接Internet资源 分析XML资源 使用Download Manager下载文件 查询Download manager 使用Account Manager 对 Google App Engine 进行身份认证 连接Internet资源 在访问internet之前,需要在应用程序清单中添加一个INTERNET uses-permission节点: <uses-permission android:name=”android.permission.INTERNET” /> String

我的Android 4 学习系列之Intent 和 Broadcast Reciever

目录 Intent 简介 使用隐式和显式Intent启动Activity.子Acitivity和Service 使用Linkify 使用Broadcast Intent 广播事件 使用 Pending Intent Intent Filter 和 Broadcast Reciever 简介 使用 Intent Filter 扩展应用程序的功能 监听 Broadcast Intent 监听设备状态改变 在运行时管理manifest Reciever Intent简介 Intent是一种消息传递机制