参考《Professional Android 4 Development》

持久化:Files, Saving State and Preferences

Android中的数据持久化

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

2. Saved UI application state: Activities和Fragment的生命周期事件中会获得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 Activity和Preference Fragment:用于host Preference Screen,在Android3.0之前,使用Preference Activity;之后使用Preference Fragment。

3. Preference Header Definition:XML文件,定义Preference Fragment和显示他们的hierarchy。

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

使用XML定义Preference Layout

定义Preference Layout的XML文件存放在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 Header的XML文件位于res/xml目录下,每个Header的Resource 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等信息,其设计目标是当Activity被runtime 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

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

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提供了两个方法:getDir和getExternalFilesDir,分别用于在应用程序文件夹内部创建文件和在文件夹外部创建文件。

创建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);
  }
}

Android 4 学习(15):持久化:Files, Saving State and Preferences的更多相关文章

  1. Android开发学习之路--数据持久化之初体验

    上班第一天,虽然工作上处于酱油模式,但是学习上依旧不能拉下,接着学习android开发吧,这里学习数据持久化的 知识. 其实数据持久化就是数据可以保存起来,一般我们保存数据都是以文件,或者数据库的形式 ...

  2. Android:日常学习笔记(9)———探究持久化技术

    Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...

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

    目录 使用Shared Preference 保留简单的应用程序数据 保存回话间的Activity实例数据 管理应用程序首选项和创建Preference Screen 保存并加载文件以及管理本地文件系 ...

  4. Redis学习——Redis持久化之AOF备份方式保存数据

    新技术的出现一定是在老技术的基础之上,并且完善了老技术的某一些不足的地方,新技术和老技术就如同JAVA中的继承关系.子类(新技术)比父类(老技术)更加的强大! 在前面介绍了Redis学习--Redis ...

  5. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  6. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  7. Android开发学习总结(一)——搭建最新版本的Android开发环境

    Android开发学习总结(一)——搭建最新版本的Android开发环境(转) 最近由于工作中要负责开发一款Android的App,之前都是做JavaWeb的开发,Android开发虽然有所了解,但是 ...

  8. android动画学习

    android动画学习   转载自:http://www.open-open.com/lib/view/open1329994048671.html 3.0以前,android支持两种动画模式,twe ...

  9. Android Animation学习(二) ApiDemos解析:基本Animatiors使用

    Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...

随机推荐

  1. IOS-社会化分享

    一.如何实现社交分享 在iOS中,实现“社交分享”的方法 1.自己编写各个平台的分享代码(代码量较多)   2.利用iOS自带的Social.framework   3.利用第三方的分享框架 友盟分享 ...

  2. ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)-mysql.sock丢失解决方案

    我们的LAMP是搭建在UBUNTU 12.04 LTS上的. LAMP是通过编译的方式进来安装的. 在一次处理意外挂机时由于未知的原因在重启后发现无法连接数据库了, 在打开网站时出现如下的的提示: E ...

  3. MySQL 5.7.3.0 安装 全程截图

    前言: 下一个班快讲MySQL数据库了,正好把服务器里面的MySQL卸了重装了一下. 截个图,作为笔记.也正好留给需要的朋友们. 目录: 下载软件 运行安装程序 安装程序欢迎界面 许可协议 查找更新 ...

  4. 剑指offer--36.整数中1出现的次数(从1到n整数中1出现的次数)

    暴力挨个数 ---------------------------------------------------------------------- 时间限制:1秒 空间限制:32768K 热度指 ...

  5. Ubuntu語言支持爲灰色修復方法

    Ubuntu語言支持爲灰色修復方法 在Ubuntu12.04中,在下不知爲何將 語言支持 中 應用到整個系統 和 添加語言 這2個按弄成了灰色,導致ibus不能輸入中文,現在唔將修復方法公告天下: 1 ...

  6. android安装apk

     * 安装apk */ private void installApk() { // 获取当前sdcard存储路径 File apkfile = new File(Environment.getE ...

  7. Freemarker 自定义标签 实现TemplateDirectiveModel

    1 自定义标签需要实现TemplateDirectiveModel这个接口中的execute方法 实例代码如下 public class UserListDirective implements Te ...

  8. CMCC有限的访问权限如何解决

    最近两天一直出现这个问题,连接CMCC-EDU的时候就是连接不上,提示有限的访问权限,什么诊断和修复IP自动获取都不管用,就是连接不上.怎么说本人也是一个电脑迷,越到这样不靠谱的问题确实不知道如何解决 ...

  9. test20181219(期末考试)

    Written with StackEdit. \(noip\)爆炸后就好久没考试了...结果今天又被抓去,感觉很慌啊... 考完了.过来填坑. T1 Description 使得\(x^x\)达到或 ...

  10. Socket通信简单实例(WCF调用Socket)

    服务端: 控制台程序监听 /// <summary> /// Server /// </summary> class Program { static Socket serve ...