Android开发存储方式详解

来源:互联网 发布:java websocket服务器 编辑:程序博客网 时间:2024/05/20 05:28

一、SharedPreferences

SharedPreferences是一种轻型数据存储方式,本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的匹配信息。

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。实现SharedPreferences存储的步骤如下:
1、获取SharedPreferences对象
2、获取SharedPreferences.Editor对象
3、通过Editor接口的putXxx方法保存key-value对,其中Xxx表示不同的数据类型。
4、通过Editor接口的commit方法保存key-value对。

//生成默认的SharedPreferences//SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);//自己定义(文件名称,权限)SharedPreferences pref = getSharedPreferences("myPref", MODE_PRIVATE);//通过Editor写入Editor editor = pref.edit();editor.putString("name", "张三");editor.putInt("age", 30);editor.putLong("time", System.currentTimeMillis());editor.putBoolean("default", true);//提交数据,每次操作之后都要提交才会生效。editor.commit();//移除数据editor.remove("default");editor.commit();//取值打印(key,默认值)System.out.println(pref.getString("name", ""));System.out.println(pref.getInt("age", 0));
二、SQLite数据库

SQLite是D.Richeard Hipp用C语言编写的开源嵌入式数据库引擎。它支持大多数的SQL92标准,并且可以在所有主的操作系统上运行。
-支持高达2TB大小的数据库
-以单个文件的形式存在
-以B-Tree的数据结构形式存储在磁盘
特点主要包括:
1、轻量级 一个动态库、单文件
2、独立性 没有依赖、无需安装
3、隔离性 全部在一个文件夹中
4、跨平台 支持众多操作系统
5、多语言接口 支持众多编程语言
6、安全性 事务处理
关于事务处理的安全性问题:
-通过数据库上的独立性和共享锁来实现独立事务处理。
-多个进程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据。
关于SQLite的数据类型:
-SQLite支持NULL、INTEGER、REAL、TEXT和BLOB数据类型
-一次代表:空值、整型值、浮点值、字符串值、二进制对象
动态数据类型(弱引用)
-当某个值插入到数据库时,SQLite将会检查他的类型,如果该类型关联的列不匹配,SQLite则会尝试将该值转换成该列的类型,如果不能转换,则该值将作为本身的类型存储。
使用须知:
-由于资源占用少、性能良好和零管理成本,嵌入式数据库有了它的用武之地。
-没有可用于SQLite的网络服务器、只能通过网络共享可能存在文件锁定或者性能问题。
-只提供数据库级的锁定。
-没有用户账户概念,而是根据文件系统确定所有数据的权限。
SQLite使用:
SQLiteDatebase:
-提供了一些管理SQLite数据库的类
-提供创建,删除、执行SQL命令,并执行其他常见的数据库管理任务的方法
-每个程序的数据库名字是唯一的

常用语句:

//执行任何SQL语句db.execSQL(String sql);//插入(表名,空列的默认值,Map)db.insert(String table, String nullColumnHack, ContentValues values);//删除(表名,删除条件,删除条件数组值),在第二个参数比较完整时,第三个参数可以不要null;db.delete(String table, String whereClause, String[] whereArgs);//更新(表名,Map,更新条件,条件数组)db.update(String table, ContentValues values, String whereClause, String[] whereArgs);//查询(表名,查询列,条件语句,条件数组,分组,分组条件,排序,分页查询条件)db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);//使用SQL语句查询db.rawQuery(sql, selectionArgs);

Cursor是Android查询数据后得到的一个管理数据集合的类,正常情况下,如果查询得到的数据量较小时不会有内存问题,而且虚拟机能够保证Cursor最终会被释放掉。然而如果Cursor的数据量特别大,特别是如果里面有Blob信息时,应该保证Cursor占用的内存被及时的释放掉,而不是等待Gabage Collection来处理。并且Android明显是倾向于编程者手动的将Cursor close掉,因为在源代码中我们发现,如果等到垃圾回收器来回收时,也就是如果不手动关闭,系统会报错,会给用户以错误提示。

Cursor:游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法getString等。常用方法:

getCount()//总记录条数isFirst()//判断是否是第一条记录isLast()//判断是否是最后一条记录moveToFirst()//移动到第一条记录moveToLast()//移动到最后一条记录move(int offset)//移动到指定记录moveToNext()//移动到下一条记录moveToPrevious()//移动到上一条记录getColumnIndexOrThrow(String columnName)//根据名称获得列索引getInt(int columnIndex)//获得指定列索引的int类型值getString(int columnIndex)//获得指定列索引的String类型值

具体使用方法参考:Android开发存储方式详解之SQLite使用实例

三、本地文件File存储

Activity的openFileOutput()方法可以用于把数据输出到文件中,创建的文件保存在/deta/data/<package name>/files目录。

//写死根目录/mnt/sdcardFile file = new File("/mnt/sdcard/test");//获取根目录Environment.getExternalStorageDirectory()File file = new File(Environment.getExternalStorageDirectory() + "/test");//如果文件不存在,创建文件if(!file.exists()){try {file.createNewFile();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else{Toast.makeText(this, "文件已经存在!", Toast.LENGTH_SHORT).show();}//删除文件file.delete();

文件权限:

MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。
MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取。
MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
从API第17开始的版本就不支持这种写法了。
MODE_PRIVATE 是数字0
MODE_WORLD_READABLE是数字1
MODE_WORLD_WRITEABLE是数字2
//这个目录是当前应用程序默认的数据存储目录File file = this.getFilesDir();//这个目录是当前应用程序默认的缓存文件的存放位置//可以把一些不是非常重要的文件在此处创建使用//如果手机内存不足的时候,系统会自动去删除APP的cache目录的数据File file = this.getCacheDir();//在/deta/data/<package name>/files目录指定权限创建文件夹(名字,权限)File file = this.getDir("test", MODE_PRIVATE);//外置存储目录this.getExternalFilesDir(type);//外置缓存目录,APP卸载数据也会清除(/mnt/sdcard/Android/data/<包名>)File file = this.getExternalCacheDir();
文件读写详情可参考:Android开发存储方式详解之本地文件读写实例
四、ContentProvider访问其他程序信息(Android四大组件之一)

其他程序通过Uri访问系统的ContentProvider数据。简单的说就是我们定义的ContentProvider是为其他应用提供数据的。系统联系人数据库存放位置如下:

/data/data/com.android.providers.conteacts/databases/contacts2.db
如何实现ContentProvider,首先必须要有一个数据库。然后执行下面方法

1、继承抽象类ContentProvider实现一系列针对数据的增、删、改、查等方法;
2、需要在AndroidMainfest.xml中完成对ContentProvider的注册。

<provider      android:name="com.cx.datastored.MyContentProvider"      android:authorities="com.cx.datastored" ></provider>
注:注册的authorities属性值时全局唯一的,一般为包名

MyContentProvider参考代码如下:

import android.content.ContentProvider;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;public class MyContentProvider extends ContentProvider {@Overridepublic int delete(Uri arg0, String arg1, String[] arg2) {//根据Uri删除arg1指定的条件所匹配的全部记录return 0;}@Overridepublic String getType(Uri arg0) {//返回当前Uri的MIME类型,如果该URI对应的数据可能包含多条记录,那么MIME类型字符串就是以vnd.android.dir开头//如果该URI对应的数据只有一条,该MIME类型字符串就是以vnd..android.cursor.item开头return null;}@Overridepublic Uri insert(Uri arg0, ContentValues arg1) {//根据Uri插入arg1对应的数据return null;}@Overridepublic boolean onCreate() {// 在ContentProvider创建后被调用return false;}@Overridepublic Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,String arg4) {//根据Uri查询出arg2指定的条件所匹配的全部记录,并且可以指定查询那些列,以什么方式(arg4)排序return null;}@Overridepublic int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {//根据Uri修改arg2指定的条件所匹配的全部记录return 0;}}

ContentProvider的使用详情请参考:Android四大组件之ContentProvider

我们在访问系统联系人,系统的ContentProvider已经写好了,我们只需要根据Uri访问ContentProvider就可以了。

Uri是指通用资源标志符。就是我们要操作的数据。
-content://com.cx.data.storeed/mycontent/#
上面结构中的四部分分别为:
1、前缀表明数据受控于一个内容提供者。它从不修改,也就是schema
2、是指在AndroidMainfest.xml中我们注册的provider中的android:authorities属性值所对应的
3、具体操作于哪个条目

4、具体指定到哪个条目下的哪条记录(#表示通配符)


我们在解析Uri的时候,有要使用到Uri解析的工具类UriMatcher类,UriMatcher使用方法如下:

//实例化,UriMatcher.NO_MATCH表示不匹配任何路径的返回码UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);//往UriMatcher类里添加一个拼凑的Uri//UriMatcher为一个Uri容器,容器里面包含着我们即将可能要操作的Uri//如果通过match()方法匹配成功就返回code值matcher.addURI("com.cx.datastored", "mycontent", 1);//首先与找通过addURI()方法添加进来的Uri匹配//匹配成功则返回设置的code(第三个参数)值,反之,返回一个UriMatcher.NO_MATCH常量(-1)matcher.match(uri);
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成。使用Activity提供的getContentResolver()方法获取ContentResolver对象。
ContentResolver类提供了与ContentProvider类相同签名的四个方法:参数完全一致
//该方法用于往ContentProvider添加数据public Uri insert(Uri uri, ContentValues values)//该方法用于从ContentProvider删除数据public Uri delete(Uri uri, String selection, String[] selectionArgs)//该方法用于更新ContentProvider中的数据public Uri update(Uri uri, ContentValues values, String selection, String[] selectionArgs)//该方法用于从ContentProvider中获取数据public Uri query(Uri uri, String[] projection, String selection, String selectionArgs, String sortOrder)
获取通讯录实例参考:使用ContentProvider添加获取通讯录信息


0 0