zoukankan      html  css  js  c++  java
  • Android 4 学习(15):持久化:Files, Saving State and Preferences

    参考《Professional Android 4 Development

    持久化:Files, Saving State and Preferences

    Android中的数据持久化

    1. Shared Preferences: 以键值对的形式存储,是一种轻量级的持久化方法。

    2. Saved UI application state: ActivitiesFragment的生命周期事件中会获得savedInstanceState参数,包含UI的内容。

    3. Files

    使用Shared Preferences

    SharedPreferences mySharedPreferences = getSharedPreferences(MY_PREFS, Activity.MODE_PRIVATE);

    MODE_PRIVATE模式的Shared Preferences存储在应用程序的sandbox里面,其他应用程序无法访问。

    修改Shared Preferences

    SharedPreferences.Editor editor = mySharedPreferences.edit();
    // Store new primitive types in the shared preferences object.
    editor.putBoolean(“isTrue”, true);
    editor.putFloat(“lastFloat”, 1f);
    editor.putInt(“wholeNumber”, 2);
    editor.putLong(“aNumber”, 3l);
    editor.putString(“textEntryValue”, “Not Empty”);
    // Commit the changes.
    editor.apply()

    读取Shared Preferences

    可以获取单个属性的值:

    // Retrieve the saved values.
    boolean isTrue = mySharedPreferences.getBoolean(“isTrue”, false);
    float lastFloat = mySharedPreferences.getFloat(“lastFloat”, 0f);
    int wholeNumber = mySharedPreferences.getInt(“wholeNumber”, 1);
    long aNumber = mySharedPreferences.getLong(“aNumber”, 0);
    String stringPreference = mySharedPreferences.getString(“textEntryValue”, “”);

    也可以将所有的键值对读到一个Map:

    Map<String, ?> allPreferences = mySharedPreferences.getAll();

    检测Shared Preferences中是否含有某个属性的值:

    boolean containsLastFloat = mySharedPreferences.contains(“lastFloat”);

    Preference Framework

    Android中的Preference Framework是基于XML的,其外观由主题决定,这样既可以使程序和系统保持一致的风格,又可以方便地继承其他程序的Preference

    Preference Framework包含四个部分:

    1. Preference Screen Layout:用于定义Preference的显示,为XML文件。

    2. Preference ActivityPreference Fragment:用于host Preference Screen,在Android3.0之前,使用Preference Activity;之后使用Preference Fragment

    3. Preference Header DefinitionXML文件,定义Preference Fragment和显示他们的hierarchy

    4. Shared Preference Change Listener: OnSharedPreferenceChangeListener接口的实现类,监听Shared PreferenceChange事件。

    使用XML定义Preference Layout

    定义Preference LayoutXML文件存放在res/xml文件夹下,下面是一个示例:

    <?xml version=”1.0” encoding=”utf-8”?>
    <PreferenceScreen xmlns:android=”http://schemas.android.com/apk/res/android”>
      <PreferenceCategory android:title=”My Preference Category”>
        <CheckBoxPreference android:key=”PREF_CHECK_BOX”
                  android:title=”Check Box Preference”
                  android:summary=”Check Box Preference Description”
                  android:defaultValue=”true”/>
      </PreferenceCategory>
    </PreferenceScreen>

    效果图:

    原生的Preference控件:

    1. CheckBoxPreference

    2. EditTextPreference

    3. ListPreference

    4. MultiSelectListPreference

    5. RingtonePreference

    使用Intent导入系统Preference

    <?xml version=”1.0” encoding=”utf-8”?>
    <PreferenceScreen xmlns:android=”http://schemas.android.com/apk/res/android”
            android:title=”Intent preference”
            android:summary=”System preference imported using an intent”>
      <intent android:action=”android.settings.DISPLAY_SETTINGS />
    </PreferenceScreen>

    Preference Fragment简介

    public class MyPreferenceFragment extends PreferenceFragment

    重写onCreate()并调用addPreferencesFromResource方法,可以Inflate Preference Fragment

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.userpreferences);
    }

    使用Preference Header定义Preference Fragment

    Preference HeaderXML文件位于res/xml目录下,每个HeaderResource ID是它的文件名(不含后缀)。

    <preference-headers xmlns:android=”http://schemas.android.com/apk/res/android”>
      <header android:fragment=”com.paad.preferences.MyPreferenceFragment”
          android:icon=”@drawable/preference_icon”
          android:title=”My Preferences”
          android:summary=”Description of these preferences” />
    </preference-headers>

    和<PreferenceScreen>类似,<preference-headers>中也可以包含Intent

    <header android:icon=”@drawable/ic_settings_display”
        android:title=”Intent”
        android:summary=”Launches an Intent.”>
      <intent android:action=”android.settings.DISPLAY_SETTINGS />
    </header>

    Preference Activity简介

    创建Preference Activity

    public class MyFragmentPreferenceActivity extends PreferenceActivity

    加载Preference Headers

    public void onBuildHeaders(List<Header> target) {
      loadHeadersFromResource(R.xml.userpreferenceheaders, target);
    }

    对于早于3.0版本的系统,可以这样:

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.userpreferences);
    }

    onSharedPreferenceChangeListener简介

    实现onSharedPreferenceChangeListener接口,可以获得Preference的添加,修改和删除事件的callback

    public class MyActivity extends Activity implements OnSharedPreferenceChangeListener {
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Register this OnSharedPreferenceChangeListener
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        prefs.registerOnSharedPreferenceChangeListener(this);
      }
      public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        // TODO Check the shared preference and key parameters and change UI or behavior as appropriate.
      }
    }

    Application Instance State持久化

    使用Shared Preferences保存Activity State

    // Create or retrieve the activity preference object.
    SharedPreferences activityPreferences = getPreferences(Activity.MODE_PRIVATE);
    // Retrieve an editor to modify the shared preferences.
    SharedPreferences.Editor editor = activityPreferences.edit();
    // Retrieve the View
    TextView myTextView = (TextView)findViewById(R.id.myTextView);
    // Store new primitive types in the shared preferences object.
    editor.putString(“currentTextValue”,
    myTextView.getText().toString());
    // Commit changes.
    editor.apply();

    借助生命周期事件保存和恢复Activity Instance State

    Activity提供了onSaveInstanceState handler来保存用户UI state等信息,其设计目标是当Activityruntime terminate后,仍可以保存UI state信息。但如果Activity是被用户关闭或通过调用finish()方法关闭,则无法保存UI state信息。

    private static final String TEXTVIEW_STATE_KEY = “TEXTVIEW_STATE_KEY”;
    @Override
    public void onSaveInstanceState(Bundle saveInstanceState) {
      // Retrieve the View
      TextView myTextView = (TextView)findViewById(R.id.myTextView);
      // Save its state
      saveInstanceState.putString(TEXTVIEW_STATE_KEY, myTextView.getText().toString());
      super.onSaveInstanceState(saveInstanceState);
    }

    这个Handler提供了在用户session里面保存UI state的方法,跨用户session还是建议使用Shared Preference

    借助生命周期事件保存和恢复Fragment Instance State

    FragmentonCreateonCreateViewonActivityCreated Handler会获得instance state bundle参数。Activity被销毁和重建时Fragment仍可以通过调用setRetainInstance方法保存自己。当Fragment调用setRetainInstance时,它将不会经历onDestroyonCreate阶段。这样可以节省很多系统资源。

    public class MyFragment extends Fragment {
      private static String USER_SELECTION = “USER_SELECTION”;
      private int userSelection = 0;
      private TextView tv;
      @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 v = inflater.inflate(R.layout.mainfragment, container, false);
        tv = (TextView)v.findViewById(R.id.text);
        setSelection(userSelection);
        Button b1 = (Button)v.findViewById(R.id.button1);
        Button b2 = (Button)v.findViewById(R.id.button2);
        Button b3 = (Button)v.findViewById(R.id.button3);
        b1.setOnClickListener(new OnClickListener() {
          public void onClick(View arg0) {
            setSelection(1);
          }
        });
        b2.setOnClickListener(new OnClickListener() {
          public void onClick(View arg0) {
            setSelection(2);
          }
        });
        b3.setOnClickListener(new OnClickListener() {
          public void onClick(View arg0) {
            setSelection(3);
          }
        });
        return v;
      }
      private void setSelection(int selection) {
        userSelection = selection;
        tv.setText(“Selected: “ + selection);
      }
      @Override
      public void onSaveInstanceState(Bundle outState) {
        outState.putInt(USER_SELECTION, userSelection);
        super.onSaveInstanceState(outState);
      }
    }

    读写静态文件

    静态文件可以放在res/raw目录下,作为资源使用。

    Resources myResources = getResources();
    InputStream myFile = myResources.openRawResource(R.raw.myfilename);

    使用应用程序自己的文件夹存储文件

    许多应用程序需要在自己的目录或其他目录中下载或创建文件。相应地,android提供了两个方法:getDirgetExternalFilesDir,分别用于在应用程序文件夹内部创建文件和在文件夹外部创建文件。

    创建Private Application Files

    String FILE_NAME = “tempfile.tmp”;
    // Create a new output file stream that’s private to this application.
    FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
    // Create a new file input stream.
    FileInputStream fis = openFileInput(FILE_NAME);

    上面代码默认的文件写模式为override,若要改为append,需将模式设为Context.MODE_APPEND。

    若要将文件设为其他应用可写,可以使用Context.MODE_WORLD_WRITEABLE模式:

    String OUTPUT_FILE = “publicCopy.txt”;
    FileOutputStream fos = openFileOutput(OUTPUT_FILE, Context.MODE_WORLD_WRITEABLE);

    获得应用的sandbox目录:

    File file = getFilesDir();
    Log.d(“OUTPUT_PATH_”, file.getAbsolutePath());

    文件缓存

    和普通文件一样,文件缓存也分为两种,内部缓存和外部缓存,分别使用getCacheDir和getExternalCacheDir获得。

    常用的文件目录

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

    如果这些默认值所对应的文件夹不存在,你可以自己去创建:

    String FILE_NAME = “MyMusic.mp3”;
    File path = Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_MUSIC);
      File file = new File(path, FILE_NAME);
      try {
        path.mkdirs();
        [... Write Files ...]
      } catch (IOException e) {
        Log.d(TAG, “Error writing “ + FILE_NAME, e);
      }
    }
  • 相关阅读:
    QOMO Linux 4.0 正式版发布
    LinkChecker 8.1 发布,网页链接检查
    pgBadger 2.1 发布,PG 日志分析
    Aletheia 0.1.1 发布,HTTP 调试工具
    Teiid 8.2 Beta1 发布,数据虚拟化系统
    zLogFabric 2.2 发布,集中式日志存储系统
    开源电子工作套件 Arduino Start Kit 登场
    Piwik 1.9 发布,网站访问统计系统
    Ruby 1.9.3p286 发布,安全修复版本
    toBraille 1.1.2 发布,Java 盲文库
  • 原文地址:https://www.cnblogs.com/jubincn/p/3462687.html
Copyright © 2011-2022 走看看