Android详细教程(基础篇):二十五、android SharedPreferences数据存储详解
对于数据的存储操作而言,Android之中一共提供了五种方式,SharedPreferences方式、文件存储方式、
SQLite数据库存储、Content Provider方式、网络存储
8.1. SharedPreferences存储数据:
多用于配置文件存储
public interface SharedPreferences |
SharedPreferences提供了一些基础的信息保存功能,所有的信息都是按照“key=value”的形式进行保存的,
但是android.content.SharedPreferences接口所保存的信息只能是一些基本的数据类型,例如:字符串、整型、
boolean等。
在讲解SharedPreferences存储方式之前,首先需要先复习一下Java中的Properties类,此类是属性的操作类,
而且在属性文件之中只能保存基本的数据类型,而且属性文件更多的情况下是作为配置文件出现的,像Strust中
的ApplicationResources.properties文件就是一个资源文件。
8.1.1. SharedPreferences接口
SharedPreferences接口的常用方法
8.1.2. SharedPreferences.Editor接口
如果现在要想进行数据的写入,则必须首先通过SharedPreferences类所提供的edit()方法才可以让其处于可编辑的操作状态,此方法返回的对象类型是android.content.SharedPreferences.Editor接口实例。
SharedPreferences.Editor接口的常用方法
8.1.3. SharedPreferences需要Activity的支持
在Android之中,想要直接操作文件,须Activity程序的支持
范例:保存文件
package com.makyan.demo; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; public class SharedPrefercenActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shared_prefercen); //第一个参数是文件名 SharedPreferences share = super.getSharedPreferences("MAKYAN", Activity.MODE_PRIVATE); //编辑文件 SharedPreferences.Editor edit = share.edit(); edit.putString("name", "yangxiongjin"); edit.putInt("age", 28); //保存文件 edit.commit(); } } |
文件被保存在android系统的一个默认路劲下:
Eclipse->window->show view->File explorer ->data->data,在你项目包的下面就存在着你保存的文件,此文件默认是以
后缀.xml结尾的。
导出此文件:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="name">yangxiongjin</string> <int name="age" value="28" /> </map> |
范例二:读取文件并显示在界面:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".SharedPrefercenActivity" > <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> |
package com.makyan.demo;
import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.widget.TextView;
public class SharedPrefercenActivity extends Activity { private TextView nameText = null; private TextView ageText = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shared_prefercen); nameText = (TextView) super.findViewById(R.id.name); ageText = (TextView) super.findViewById(R.id.age); //第一个参数是文件名 SharedPreferences share = super.getSharedPreferences("MAKYAN", Activity.MODE_PRIVATE); nameText.setText("作者姓名:" + share.getString("name", "")); ageText.setText("作者年龄:" + share.getInt("age", 0)); } } |
8.2. 文件存储
如果要进行文件的输入或输出操作,都需要对IO进行操作
回顾IO流输出/输入文件的流程:
- 使用File类定义一个要操作的文件
- 使用字节流或字符流的子类为父类进行实例化,因为四个IO流的操作都是抽象类
- 完成输入/输出的功能
- 关闭流
- 流的继承关系:
- 操作流的几条原则:
- 不管是输入还是输出流,使用完毕后要close(),如果是带有缓冲区的输出流,应在关闭前调用flush()。
- 应该尽可能使用缓冲区,来减少IO次数,以提高性能。
- 能用字符流处理的不用字节流。
Android中文件存储常用的包括:
- Android提供的资源存储
- XML文件存储:
解析XML文件的方式:
- DOM解析、读取
- SAX解析、读取
- XML.PULL解析
- JSON数据保存、解析
8.3. Content Provider
Android之中一共有四大组件,Activity、ContentProvider、Intent、Service。
在开发之中,用户自定义的ContentProvider的形式比较少见,但是往往会使用大量系统中提供的ContentProvider。
本章目标:
- 掌握ContentProvider的主要作用及操作形式
- 可以使用ContentProvider进行程序的开发
- 可以使用内建的ContentProvider进行其他应用程序的数据操作
- 可以使用SimpleCursorAdapter进行数据的显示操作。
8.3.1. ContentProvider要解决的问题-解决不同应用程序之间的数据访问:
在Android当中,每一个应用程序的数据都是采用私有的形式进行操作的,不管这些数据是文件保存还是数据库保存,
都不能被外部应用程序所访问。但是在很多情况下用户是需要可以在不同的应用程序之间进行数据的交换,所以为了
解决这样的问题,在Android中专门提供了ContentProvider类,此类的主要功能是将不同的应用程序的数据操作标准
统一起来,并且将各个应用程序的数据操作标准暴露给其他应用程序,这样,一个应用程序的数据就可以按照
ContentProvider所制定的标准被外部所操作。
8.3.2. ContentProvider类常用的操作方法
Package:android.content public abstract class ContentProvider extends Object implements ComponentCallbacks |
8.3.3. Uri—提供了访问数据的地址
package:android.net public abstract class Uri extends Object implements Parcelable Comparable<T> |
B部分也可以不使用”包.类”
8.3.4. ContentResolver—提供了一个操作的标准
package:android.content public abstract class ContentResolver extends Object |
这里面的操作方法与ContentProvider是完全一样的。
如果要想操作ContentResolver,那么也需要Activity程序的支持
8.3.5. ContentUris—Uri的辅助操作类
8.3.6. UriMatcher—Uri的辅助操作类(Uri的匹配)
有可能是多个URL进入到一个操作方法,而后使用match()进行匹配,以决定调用那一个
ContentProvider操作示意图:
- 开发ContentProvider程序
8.3.7. ContentProvider总结:
android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。这些数据可以存储
在文件系统中、在一个SQLite数据库、或以任何其他合理的方式,
其他应用可以通过ContentResolver类(见ContentProviderAccessApp例子)从该内容提供者中获取或存入数据.
(相当于在应用外包了一层壳),
只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存
储在一个内容提供者中
它的好处:统一数据访问方式。
android 系统自带的内容提供者(顶级的表示数据库名,非顶级的都是表名)这些内容提供者在SDK文档的
android.provider Java包中都有介绍。见:
http://developer.android.com/reference/android/provider /package-summary.html
├────Browser
├────CallLog
├────Contacts
│ ├────Groups
│ ├────People
│ ├────Phones
│ └────Photos
├────Images
│ └────Thumbnails
├────MediaStore
│ ├────Albums
│ ├────Artists
│ ├────Audio
│ ├────Genres
│ └────Playlists
├────Settings
└────Video
CallLog:地址和接收到的电话信息
Contact.People.Phones:存储电话号码
Setting.System:系统设置和偏好设置
使用Content Provider对外共享数据的步骤:
1> 继承ContentProvider类并根据需求重写以下方法:
public boolean onCreate();//处理初始化操作 /** * 插入数据到内容提供者(允许其他应用向你的应用中插入数据时重写) * @param uri * @param initialValues 插入的数据 * @return */ public Uri insert(Uri uri, ContentValues initialValues);
/** * 从内容提供者中删除数据(允许其他应用删除你应用的数据时重写) * @param uri * @param selection 条件语句 * @param selectionArgs 参数 * @return */ public int delete(Uri uri, String selection, String[] selectionArgs);
/** * 更新内容提供者已存在的数据(允许其他应用更新你应用的数据时重写) * @param uri * @param values 更新的数据 * @param selection 条件语句 * @param selectionArgs 参数 * @return */ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
/** * 返回数据给调用者(允许其他应用从你的应用中获取数据时重写) * @param uri * @param projection 列名 * @param selection 条件语句 * @param selectionArgs 参数 * @param sortOrder 排序 * @return */ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) ;
/** * 用于返回当前Uri所代表数据的MIME类型 * 如果操作的数据为集合类型(多条数据),那么返回的类型字符串应该为vnd.android.cursor.dir/开头 * 例如要得到所有person记录的Uri为content://com.bravestarr.provider.personprovider/person, * 那么返回的MIME类型字符串应该为"vnd.android.cursor.dir/person" * 如果操作的数据为单一数据,那么返回的类型字符串应该为vnd.android.cursor.item/开头 * 例如要得到id为10的person记录的Uri为content://com.bravestarr.provider.personprovider/person/10, * 那么返回的MIME类型字符串应该为"vnd.android.cursor.item/person" * @param uri */ public String getType(Uri uri) |
这些方法中的Uri参数,得到后需要进行解析然后做对应处理,Uri表示要操作的数据,包含两部分信息:
1.需要操作的contentprovider
2.对contentprovider中的什么数据进行操作,一个Uri格式:结构头://authorities(域名)/路径
(要操作的数据,根据业务而定)
content://com.bravestarr.provider.personprovider/person/10
说明:
结构头:contentprovider的结构头已经由android规定为content://
Authorities:用于唯一标识这个contentprovider程序,外部调用者可以根据这个找到他
路径:表示我们要操作的数据,路径的构建根据业务而定.路径格式如下:
要操作person表行号为10的记录,可以这样构建/person/10
要操作person表的所有记录,可以这样构建/person
2 > 在AndroidManifest.xml中使用<provider>对ContentProvider进行配置注册(内容提供者注册它自己
就像网站注册域名),ContentProvider采用authoritie(原意授权,可理解为域名)作为唯一标识,方便其他应
用能找到
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <!-- authorities属性命名建议:公司名.provider.SomeProvider--> <provider android:name=".PersonProvider" android:authorities="com.bravestarr.provider.personprovider"/> ... </application> |