SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。

主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常规的Long长 整形、Int整形、String字符串型的保存。

SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs目录下:

分析以下几个方法:

Android中得到SharedPreference的方式有四种:

  • ContextWrapper.getSharedPreferences(String name, int mode)
  • Activity.getPreferences(int mode)
  • PreferenceManager.getSharedPreferences()
  • PreferenceManager.getDefaultSharedPreferences(Context context)

下面我们一起来跟踪下它们的源码:
1.ContextWrapper.getSharedPreferences(String name,int mode)
 
可以看出,我们可以自己设置SharedPreference的名字与模式

一、getSharedPreferences(name,mode)

方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Android自动加上;

方法的第二个参数指定文件的操作模式,共有四种操作模式。

四种操作模式分别为:

1. MODE_APPEND: 追加方式存储

2. MODE_PRIVATE: 私有方式存储,其他应用无法访问

3. MODE_WORLD_READABLE: 表示当前文件可以被其他应用读取

4. MODE_WORLD_WRITEABLE: 表示当前文件可以被其他应用写入

二、edit()方法获取editor对象

Editor editor = sharedPreferences.edit();

editor存储对象采用key-value键值对进行存放,editor.putString("name", "wujaycode");

通过commit()方法提交数据

与之对应的获取数据的方法:

SharedPreferences share=getSharedPreferences("Acitivity",Activity.MODE_WORLD_READABLE);

int i=share.getInt("i",0);

String str=share.getString("str","");

boolean flag=share.getBoolean("flag",false);

getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值

如果你想要删除通过SharedPreferences产生的文件,可以通过以下方法:

File file= new File("/data/data/"+getPackageName().toString()+"/shared_prefs","Activity.xml");

if(file.exists()){

file.delete();

Toast.makeText(TestActivity.this, "删除成功", Toast.LENGTH_LONG).show(); }

三、访问其他应用中的Preference

如果要访问其他应用中的Preference,必须满足的条件是,要访问的应用的Preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。

举例,假如有个<package name>为com.wujay.action下面的应用使用了下面语句创建了Preference,getSharedPreferences("wujay", Context.MODE_WORLD_READABLE),

现在要访问该Preferences:

首先,需要创建上面的Context,然后通过Context访问Preferences,访问preference时会在应用所在包下的shared_prefs目录找到preference:

Context otherAppsContext = createPackageContext("com.wujay.action", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences("wujay", Context.MODE_WORLD_READABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 0);

如果不通过创建Context访问其他应用的preference,可以以读取xml文件方式直接访问其他应用preference对应的xml文件,如:
File xmlFile = new File(“/data/data/<package name>/shared_prefs/itcast.xml”);//<package name>应替换成应用的包名。

2.Activity.getPreferences(int mode)
 
这种方式下,name是通过getLocalClassName()得到的,不能让我们自己设置,而且最终会调到ContextWrapper的getSharedPreferences(),getLocalClassName()定义如下:

3.PreferenceManager.getSharedPreferences()
 
这种方式我们是让PreferenceManager给我们维护一个SharedPreference,当然我们可以调用PreferenceManager的API来设置name和mode,并且最终也是调用到ContextWrapper的getSharedPreferences
4.PreferenceManager.getDefaultSharedPreferences(Context context)
 
这种方式得到的SharedPreference是某个包名下共享的,并且是私有的,不能让其他的包访问,而且Name和mode不能设置。最终也会调用到ContextWrapper的getSharedPreferences

总结:

获取SharedPreferences的两种方式:
1 调用Context对象的getSharedPreferences()方法
2 调用Activity对象的getPreferences()方法
两种方式的区别:
调用Context对象的getSharedPreferences()方法获得的SharedPreferences对象可以被同一应用程序下的其他组件共享.
调用Activity对象的getPreferences()方法获得的SharedPreferences对象只能在该Activity中使用.
 
 

使用方法

1、存数据

 SharedPreferences sp = getSharedPreferences("sp_demo", Context.MODE_PRIVATE);
sp.edit().putString("name", "小张").putInt("age", 11).commit();

或者下面的写法也可以

 SharedPreferences sp = getSharedPreferences("sp_demo", Context.MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString("name", "小张");
editor.putInt("age", 11);
editor.commit();

切记不要写成下面的形式,会导致数据无法存储

 SharedPreferences sp = getSharedPreferences("sp_demo", Context.MODE_PRIVATE);
sp.edit().putString("name", "小张");
sp.edit().putInt("age", 11);
sp.edit().commit();

为什么这种方式无法存储,因为sp.edit()每次都会返回一个新的Editor对象,Editor的实现类EditorImpl里面会有一个缓存的Map,最后commit的时候先将缓存里面的Map写入内存中的Map,然后将内存中的Map写进XML文件中。使用上面的方式commit,由于sp.edit()又重新返回了一个新的Editor对象,缓存中的Map是空的,所以导致数据无法被存储。

2、取数据

 SharedPreferences sp = getSharedPreferences("sp_demo", Context.MODE_PRIVATE);
String name = sp.getString("name", null);
int age = sp.getInt("age", 0);

getSharedPreferences的具体实现是在frameworks/base/core/java/android/app/ContextImpl.java,代码如下:

 @Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
synchronized (ContextImpl.class) {
......
final String packageName = getPackageName();
ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
if (packagePrefs == null) {
packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
sSharedPrefs.put(packageName, packagePrefs);
} ......
sp = packagePrefs.get(name);
if (sp == null) {
File prefsFile = getSharedPrefsFile(name);
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;
}
}
......
return sp;
}

SharedPreferencesImpl是SharedPreferences接口的具体实现类,一个name对应一个SharedPreferencesImpl,一个应用程序中根据name的不同会有多个SharedPreferencesImpl。 
SharedPreferencesImpl的具体实现是在frameworks/base/core/java/android/app/SharedPreferencesImpl.java,我们可以通过getSharedPreferences获得

SharedPreferences sharedPreferences = getSharedPreferences("ljq", Context.MODE_PRIVATE);

//getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值

String name = sharedPreferences.getString("name", "");

int age = sharedPreferences.getInt("age", 1);

如果访问其他应用中的Preference,前提条件是:该preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。

如:有个<package name>为com.ljq.action的应用使用下面语句创建了preference。

getSharedPreferences("ljq", Context.MODE_WORLD_READABLE);

其他应用要访问上面应用的preference,首先需要创建上面应用的Context,然后通过Context 访问preference ,访问preference时会在应用所在包下的shared_prefs目录找到preference :

Context otherAppsContext = createPackageContext("com.ljq.action", Context.CONTEXT_IGNORE_SECURITY);

SharedPreferences sharedPreferences = otherAppsContext.getSharedPreferences("ljq", Context.MODE_WORLD_READABLE);

String name = sharedPreferences.getString("name", "");

int age = sharedPreferences.getInt("age", 0);

如果不通过创建Context访问其他应用的preference,也可以以读取xml文件方式直接访问其他应用preference对应的xml文件,如:

File xmlFile = new File("/data/data/<package name>/shared_prefs/itcast.xml");//<package name>应替换成应用的包名

案例:

string.xml文件

 <?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, SpActivity!</string>
<string name="app_name">软件配置参数</string>
<string name="name">姓名</string>
<string name="age">年龄</string>
<string name="button">保存设置</string>
<string name="showButton">显示</string>
</resources>

main.xml布局文件

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/name"
android:textSize="20px"
android:id="@+id/nameLable" />
<EditText android:layout_width="80px"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/nameLable"
android:layout_alignTop="@id/nameLable"
android:layout_marginLeft="10px"
android:id="@+id/name" />
</RelativeLayout>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20px"
android:text="@string/age"
android:id="@+id/ageLable" />
<EditText android:layout_width="80px"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/ageLable"
android:layout_alignTop="@id/ageLable"
android:layout_marginLeft="10px"
android:id="@+id/age" />
</RelativeLayout>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
android:id="@+id/button" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/showButton"
android:layout_toRightOf="@id/button"
android:layout_alignTop="@id/button"
android:id="@+id/showButton" />
</RelativeLayout>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20px"
android:id="@+id/showText" />
</LinearLayout>
 package com.ljq.activity;

 import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; public class SpActivity extends Activity {
private EditText nameText;
private EditText ageText;
private TextView resultText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); nameText = (EditText)this.findViewById(R.id.name);
ageText = (EditText)this.findViewById(R.id.age);
resultText = (TextView)this.findViewById(R.id.showText); Button button = (Button)this.findViewById(R.id.button);
Button showButton = (Button)this.findViewById(R.id.showButton);
button.setOnClickListener(listener);
showButton.setOnClickListener(listener); // 回显
SharedPreferences sharedPreferences=getSharedPreferences("ljq123",
Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
String nameValue = sharedPreferences.getString("name", "");
int ageValue = sharedPreferences.getInt("age", 1);
nameText.setText(nameValue);
ageText.setText(String.valueOf(ageValue));
} private View.OnClickListener listener = new View.OnClickListener(){
public void onClick(View v) {
Button button = (Button)v;
//ljq123文件存放在/data/data/<package name>/shared_prefs目录下
SharedPreferences sharedPreferences=getSharedPreferences("ljq123",
Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
switch (button.getId()) {
case R.id.button:
String name = nameText.getText().toString();
int age = Integer.parseInt(ageText.getText().toString());
Editor editor = sharedPreferences.edit(); //获取编辑器
editor.putString("name", name);
editor.putInt("age", age);
editor.commit();//提交修改
Toast.makeText(SpActivity.this, "保存成功", Toast.LENGTH_LONG).show();
break;
case R.id.showButton:
String nameValue = sharedPreferences.getString("name", "");
int ageValue = sharedPreferences.getInt("age", 1);
resultText.setText("姓名:" + nameValue + ",年龄:" + ageValue);
break;
}
}
};
}

运行结果

如何访问其他应用中的Preference?

 package com.ljq.sp;

 import java.io.File;
import java.io.FileInputStream; import android.content.Context;
import android.content.SharedPreferences;
import android.test.AndroidTestCase;
import android.util.Log; public class AccessSharePreferenceTest extends AndroidTestCase{
private static final String TAG = "AccessSharePreferenceTest"; /**
* 访问SharePreference的方式一,注:权限要足够
* @throws Exception
*/
public void testAccessPreference() throws Exception{
String path = "/data/data/com.ljq.activity/shared_prefs/ljq123.xml";
File file = new File(path);
FileInputStream inputStream = new FileInputStream(file);
//获取的是一个xml字符串
String data = new FileService().read(inputStream);
Log.i(TAG, data);
} /**
* 访问SharePreference的方式二,注:权限要足够
* @throws Exception
*/
public void testAccessPreference2() throws Exception{
Context context = this.getContext().createPackageContext("com.ljq.activity",
Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = context.getSharedPreferences("ljq123",
Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 1);
Log.i(TAG, name + " : " +age);
}
}

[ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据的更多相关文章

  1. Android五种数据存储方式

    android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...

  2. Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据

    本来这篇文章在昨天晚上就能发布的,悲剧的是写了两三千字的文章居然没保存,结果我懵逼了.今天重新来写这篇文章.今天我们就一起来探讨下如何重写Ocelot配置文件的存储方式以及获取方式. 作者:依乐祝 原 ...

  3. Android 四种加载方式详解(standard singleTop singleTask singleInstance) .

    Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...

  4. C++动态存储方式与静态存储方式

    如果从变量值存在的时间(即生存期)来分,可将程序中的变量分为:动态存储方式和静态存储方式.它们所占用的存储空间区域不同. C++存储空间区域 代码区:存放可执行程序的程序代码.静态存储区:存放静态变量 ...

  5. [ Android 五种数据存储方式之四 ] —— ContentProvider存储数据

    Android这个系统和其他的操作系统还不太一样,我们需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据.那这个时候有读者就会提出问题,难道两个 ...

  6. Android数据存储方式之SharedPreferences

    Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数.使用SharedPreferences保存数据,其背后是用xml文件存放数 ...

  7. android开发之路11(用SharedPreferences存储数据)

    Android平台给我们提供了一个SharedPreferences类,实际上SharedPreferences处理的就是一个key-value(键值对),它是 一个轻量级的存储类,特别适合用于保存软 ...

  8. Android四种点击事件和五中存储方式

    Android点击事件的四种实现方式 1.内部类实现onClickListenter接口 bt_login.setOnClickListener(new MyListener()); class My ...

  9. 【Android】数据的应用-使用sharedpreferences存储数据

    Android应用开发SharedPreferences存储数据的使用方法 SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的 ...

随机推荐

  1. Block 进阶

    转载自:http://www.cnblogs.com/xiaofeixiang/p/4666796.html 关于Block之前有一篇文章已经写过一篇文章Object-C-代码块Block回顾,不过写 ...

  2. Android--->activity界面跳转,以及查看生命周期过程

    main.xml界面布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ...

  3. 文件I/O的操作实例

    1_open.c: #include <sys/types.h> #include <stdio.h> #include <sys/stat.h> #include ...

  4. 首页布局时div的宽度设置要注意

  5. Xcode制作插件

    转发至:https://onevcat.com/2013/02/xcode-plugin/ Xcode 4 插件制作入门 本文欢迎转载,但烦请保留此行出处信息:http://www.onevcat.c ...

  6. vm10虚拟机安装Mac OS X10.10教程

    VM10装Mac OS X 10.9.3及更新到Mac OS X 10.10,让你的windows也能玩Swift .  最近WWDC放出终极大招——新的编程语言Swift(雨燕),导致一大波程序员的 ...

  7. CodeForces 621C Wet Shark and Flowers

    方法可以转化一下,先计算每一个鲨鱼在自己范围内的数能被所给素数整除的个数有几个,从而得到能被整除的概率,设为f1,不能被整除的概率设为f2. 然后计算每相邻两只鲨鱼能获得钱的期望概率,f=w[id1] ...

  8. ReactiveNative学习之Diff算法

    React 源码剖析系列 - 不可思议的 react diff深入浅出React(四):虚拟DOM Diff算法解析React diff 算法总结链接引用的文章React出于性能的考虑,为了避免频繁操 ...

  9. Nginx安装及配置虚拟主机

    nginx安装部分 依赖环境 yum -y install gcc zlib openssl-devel zlib-devel 1. 下载好下面两个包:nginx-1.8.1.tar.gz pcre- ...

  10. 内置Web Server

    在终端输入命令:php -S localhost:8000 -t xxx(某个目录或文件) 这个内置的Web服务器主要用于本地开发使用,不可用于线上产品环境. URI请求会被发送到PHP所在的的工作目 ...