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);
      }
    }
  • 相关阅读:
    python实例26[查询修改文件的属性]
    [SCM]源码管理 VisualSVN Server+TortoiseSVN
    持续集成之“依赖管理”
    Spoon:在“云”上运行桌面应用程序
    数字签名的验证
    判断Linux/Unix为32位或64位
    持续集成理论和实践的新进展
    [SCM]源码管理 SVN Server
    [BuildRelease Management]Parabuild
    为VM增加磁盘空间
  • 原文地址:https://www.cnblogs.com/jubincn/p/3462687.html
Copyright © 2011-2022 走看看