• 我的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。

    Screenshot_2014-09-10-10-55-59

    (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)效果运行:

    Screenshot_2014-09-11-13-23-10

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

    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

    这一张搞完唉。

  • 相关阅读:
    Matlab中使用Java api画图图形并保存为jpeg格式
    基于注解的Mybatis mapper 接口注意事项
    Chap 2 Representing and Manipulating Information (CS:APP)
    设计模式之享元模式
    辛星浅析Linux中的postfix
    ZOJ 1364 Machine Schedule(二分图最大匹配)
    Scrapy系列教程(3)------Spider(爬虫核心,定义链接关系和网页信息抽取)
    恩布企业 IM iOS端 1.1 公布, 开源手机 IM
    leetcode_Power of Two_easy
    小强的HTML5移动开发之路(45)——汇率计算器【1】
  • 原文地址:https://www.cnblogs.com/jtxs/p/3961813.html
Copyright © 2020-2023  润新知