zoukankan      html  css  js  c++  java
  • [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据

    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)
    ContextWrapper.getSharedPreferences.jpg 
    可以看出,我们可以自己设置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)
    Activity.getPreferences.jpg 
    这种方式下,name是通过getLocalClassName()得到的,不能让我们自己设置,而且最终会调到ContextWrapper的getSharedPreferences(),getLocalClassName()定义如下:
    Activity.getLocalClassName.jpg 

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

    总结:

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

    使用方法

    1、存数据

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

    或者下面的写法也可以

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

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

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

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

    2、取数据

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

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

     1 @Override
     2 public SharedPreferences getSharedPreferences(String name, int mode) {
     3     SharedPreferencesImpl sp;
     4     synchronized (ContextImpl.class) {
     5         ......
     6         final String packageName = getPackageName();
     7         ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
     8         if (packagePrefs == null) {
     9             packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
    10             sSharedPrefs.put(packageName, packagePrefs);
    11         }
    12 
    13         ......
    14         sp = packagePrefs.get(name);
    15         if (sp == null) {
    16             File prefsFile = getSharedPrefsFile(name);
    17             sp = new SharedPreferencesImpl(prefsFile, mode);
    18             packagePrefs.put(name, sp);
    19             return sp;
    20         }
    21     }
    22     ......
    23     return sp;
    24 }

    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文件

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

    main.xml布局文件

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:orientation="vertical" 
     4     android:layout_width="fill_parent"
     5     android:layout_height="fill_parent">
     6     <RelativeLayout
     7         xmlns:android="http://schemas.android.com/apk/res/android"
     8         android:layout_width="wrap_content"
     9         android:layout_height="wrap_content">
    10         <TextView android:layout_width="wrap_content"
    11             android:layout_height="wrap_content" 
    12             android:text="@string/name"
    13             android:textSize="20px"
    14             android:id="@+id/nameLable" />
    15         <EditText android:layout_width="80px"
    16             android:layout_height="wrap_content" 
    17             android:layout_toRightOf="@id/nameLable"
    18             android:layout_alignTop="@id/nameLable"
    19             android:layout_marginLeft="10px"
    20             android:id="@+id/name" />
    21     </RelativeLayout>
    22     <RelativeLayout
    23         xmlns:android="http://schemas.android.com/apk/res/android"
    24         android:layout_width="wrap_content"
    25         android:layout_height="wrap_content">
    26         <TextView android:layout_width="wrap_content"
    27             android:layout_height="wrap_content" 
    28             android:textSize="20px"
    29             android:text="@string/age"
    30             android:id="@+id/ageLable" />
    31         <EditText android:layout_width="80px"
    32             android:layout_height="wrap_content" 
    33             android:layout_toRightOf="@id/ageLable"
    34             android:layout_alignTop="@id/ageLable"
    35             android:layout_marginLeft="10px"
    36             android:id="@+id/age" />
    37     </RelativeLayout>
    38     <RelativeLayout
    39         xmlns:android="http://schemas.android.com/apk/res/android"
    40         android:layout_width="wrap_content"
    41         android:layout_height="wrap_content">
    42         <Button android:layout_width="wrap_content"
    43             android:layout_height="wrap_content" 
    44             android:text="@string/button"
    45             android:id="@+id/button" />
    46         <Button android:layout_width="wrap_content"
    47             android:layout_height="wrap_content" 
    48             android:text="@string/showButton"
    49             android:layout_toRightOf="@id/button"
    50             android:layout_alignTop="@id/button"
    51             android:id="@+id/showButton" />
    52     </RelativeLayout>
    53     <TextView android:layout_width="fill_parent"
    54             android:layout_height="wrap_content" 
    55             android:textSize="20px"
    56             android:id="@+id/showText" />
    57 </LinearLayout>
     1 package com.ljq.activity;
     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.view.View;
     9 import android.widget.Button;
    10 import android.widget.EditText;
    11 import android.widget.TextView;
    12 import android.widget.Toast;
    13 
    14 public class SpActivity extends Activity {
    15     private EditText nameText;
    16     private EditText ageText;
    17     private TextView resultText;
    18     @Override
    19     public void onCreate(Bundle savedInstanceState) {
    20         super.onCreate(savedInstanceState);
    21         setContentView(R.layout.main);
    22         
    23         nameText = (EditText)this.findViewById(R.id.name);
    24         ageText = (EditText)this.findViewById(R.id.age);
    25         resultText = (TextView)this.findViewById(R.id.showText);
    26         
    27         Button button = (Button)this.findViewById(R.id.button);
    28         Button showButton = (Button)this.findViewById(R.id.showButton);
    29         button.setOnClickListener(listener);
    30         showButton.setOnClickListener(listener);
    31         
    32         // 回显
    33         SharedPreferences sharedPreferences=getSharedPreferences("ljq123", 
    34                 Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
    35         String nameValue = sharedPreferences.getString("name", "");
    36         int ageValue = sharedPreferences.getInt("age", 1);
    37         nameText.setText(nameValue);
    38         ageText.setText(String.valueOf(ageValue));
    39     }
    40     
    41     private View.OnClickListener listener = new View.OnClickListener(){
    42         public void onClick(View v) {
    43             Button button = (Button)v;
    44             //ljq123文件存放在/data/data/<package name>/shared_prefs目录下
    45             SharedPreferences sharedPreferences=getSharedPreferences("ljq123", 
    46                     Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
    47             switch (button.getId()) {
    48             case R.id.button:
    49                 String name = nameText.getText().toString();
    50                 int age = Integer.parseInt(ageText.getText().toString());
    51                 Editor editor = sharedPreferences.edit(); //获取编辑器
    52                 editor.putString("name", name);
    53                 editor.putInt("age", age);
    54                 editor.commit();//提交修改
    55                 Toast.makeText(SpActivity.this, "保存成功", Toast.LENGTH_LONG).show();
    56                 break;
    57             case R.id.showButton:
    58                 String nameValue = sharedPreferences.getString("name", "");
    59                 int ageValue = sharedPreferences.getInt("age", 1);
    60                 resultText.setText("姓名:" + nameValue + ",年龄:" + ageValue);
    61                 break;
    62             }
    63         }
    64     };
    65 }

    运行结果

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

     1 package com.ljq.sp;
     2 
     3 import java.io.File;
     4 import java.io.FileInputStream;
     5 
     6 import android.content.Context;
     7 import android.content.SharedPreferences;
     8 import android.test.AndroidTestCase;
     9 import android.util.Log;
    10 
    11 public class AccessSharePreferenceTest extends AndroidTestCase{
    12     private static final String TAG = "AccessSharePreferenceTest";
    13     
    14     /**
    15      * 访问SharePreference的方式一,注:权限要足够
    16      * @throws Exception
    17      */
    18     public void testAccessPreference() throws Exception{
    19         String path = "/data/data/com.ljq.activity/shared_prefs/ljq123.xml";
    20         File file = new File(path);
    21         FileInputStream inputStream = new FileInputStream(file);
    22         //获取的是一个xml字符串
    23         String data = new FileService().read(inputStream);
    24         Log.i(TAG, data);
    25     }
    26     
    27     /**
    28      * 访问SharePreference的方式二,注:权限要足够
    29      * @throws Exception
    30      */
    31     public void testAccessPreference2() throws Exception{
    32         Context context = this.getContext().createPackageContext("com.ljq.activity", 
    33                 Context.CONTEXT_IGNORE_SECURITY);
    34         SharedPreferences sharedPreferences = context.getSharedPreferences("ljq123", 
    35                 Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
    36         String name = sharedPreferences.getString("name", "");
    37         int age = sharedPreferences.getInt("age", 1);
    38         Log.i(TAG, name + " : " +age);
    39     }
    40 }
  • 相关阅读:
    Leetcode 3. Longest Substring Without Repeating Characters/ 4. Median of Two Sorted Arrays[二分]
    最大流算法思想和理论的简单理解
    数值线性代数实验-共轭梯度法
    运筹学上机实验
    HDU 1542 Atlantis[扫描线]
    数值实验-高斯消元LU分解
    PAT 1143-Lowest Common Ancestor (30) 二叉树还原
    L2-006. 树的遍历
    hdu-3038 How Many Answers Are Wrong[并查集]
    poj-3253 Fence Repair[霍夫曼树]
  • 原文地址:https://www.cnblogs.com/Im-Victor/p/6288658.html
Copyright © 2011-2022 走看看