前言

  最近在学习《第一行android代码》和《疯狂android讲义》,我的感触是Android应用的本质其实就是数据的处理,包括数据的接收,存储,处理以及显示,我想针对这几环分别写一篇博客,记得我的学习心得,也希望跟各位新手同学相互努力促进。今天这篇博客,我想介绍一下数据的存储,因为数据的接收,存储,处理以及显示这几环环环相扣,而数据的存储直接关系到数据的处理和显示,所以显得尤为重要。

  所以本文针对数据存储的常见方案和其使用进行了归纳。分为程序内存储和程序间数据访问,程序内存储介绍了文件存储、SharedPreferences存储、数据库存储三种不同的存储方式的优缺点以及区别,用用例子详细说明了各自的用法,重点介绍了数据库存储的操作。 程序间数据访问介绍了内容提供器。

Android程序内数据存储方案:

  Android系统中主要提供了三种方式用于简单地实现数据持久化功能,即文件存储、SharedPreferences存储以及数据库存储。当然,除了这三种方式之外,还可以将数据保存在手机的SD卡中,不过使用文件存储、SharedPreferences存储以及数据库存储会相对于将数据保存在手机的SD卡中更安全也更简单一些[1]

  一、文件存储:

  文件存储是Android中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。如果你想使用文件存储的方式来保存一些较为复杂的文本数据,就需要定义一套自己的格式规范,这样方便于之后将数据从文件中重新解析出来。由于文件存储的方式有着起局限性,在实际工程项目中用的很少,我们也就不具体展开说。

  二、SharedPreferences存储:

  不同于文件的存储方式,SharedPreference是使用键值对的方式来存储数据的。也就是说当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且SharedPreferences还支持多种不同的数据类型存储,这就是SharedPreference比文件存储的优越性所在。

三种获取SharedPreferences对象的方法

  • Context类中的getSharedPreferences()方法

        SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);

  第一个参数用于指定SharedPreferences文件的名称。第二个参数指定操作模式,MODE_PRIVATE表示只有当前的应用程序才可以对这个SharedPreferences进行读写,MODE_MULTI_PROCESS则一般用于会有多个进程中对同一个SharedPreferences文件进行读写的情况。

  • Activity类中的getPreferences()方法

  跟Context类中的getSharedPreferences()方法很相似,不过只接受一个操作模式参数

  • PreferenceManager类中的getDefaultSharedPreferences()方法

        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);

  这是一个静态方法,接收Context参数。

例子:通过SharedPreferences进行读写数据

shareRead = (Button) findViewById(R.id.share_read);
shareWrite = (Button) findViewById(R.id.share_write);
/**
* pref = PreferenceManager.getDefaultSharedPreferences(this);
*/
pref = getSharedPreferences("data", MODE_PRIVATE);
editor = pref.edit();
shareWrite.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
editor.putString("write", "This is A String");
/*数据提交*/
editor.commit();
}
});
shareRead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String str = pref.getString("write", null);
Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
}
});

  

  • 存储数据(shareWrite)的实现

  1. 调用SharedPreferences对象的Edit()方法获取一个SharedPreferences.Editor对象

  2. 向SharedPreferences.Editor对象中添加数据,采用putBoolean、putString等方法

  3. 调用commint()方法将添加的数据提交

  • 获取数据(shareRead)的实现

  1. 直接采用SharedPreferences对象的get方法

  2. get方法接收两个参数,第一个是键,第二个参数是默认值,当传入的键找不大到对应的值,返回默认值

效果图

   

  sharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其只能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式[2]

  三、数据库存储

创建数据库: SQLiteDatabase.execSQL()

public class MyDatabaseHelper extends SQLiteOpenHelper {
/*建立一个student的数据表*/
public static final String CREATE_STUDENT = "create table student ("
+ "id integer primary key autoincrement,"
+ "number integer,"
+ "name text,"
+ "major text)"; private Context myContext; public MyDatabaseHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
myContext = context;
} @Override
public void onCreate(SQLiteDatabase db) {
/*创建数据库*/
db.execSQL(CREATE_STUDENT);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

更新数据库:onUpgrade()

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
/*drop table if exists student:发现数据库已经存在student这张表就删除*/
db.execSQL("drop table if exists student");
onCreate(db);
}

当表中没有我们所要的数据时:

添加数据:insert(String table, String nullColumnHack, ContentValues values)

MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "student.db, null, 2");
SQLiteDatabase db = dbHelper. getWritableDatabase();
ContentValues values = new ContentValues();
values.put("number", 123456);
values.put("name", "steve");
values.put("major", "CS");
db.insert("student", null, values);

当表中数据已经存在,但是数据需要修改:

更新数据:update(String table, ContentValues values, String whereClause, String[] whereArgs)

db.update("student", values,  "name = ?", new String[]{"steve"});

     删除数据:delete(String table, String whereClause, String[] whereArgs)

db.delete("student", "name = ?", new String[]{"steve"});

查询数据:

Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy)    

     Cursor rawQuery(String sql, String[] selectionArgs) 

查询表

query()方法参数 对应SQL部分 描述
table from table_name 指定查询的表明
columns select column1,column2 指定查询的列名
selection where column = value 指定where的约束条件
selectionArgs - 为where中的占位符提供具体的值
groupBy group by column 指定需要group by的列
having having column = value 对group by后的结果进一步约束
orderBy order by column1, column2 指定查询结果的排序方式
Cursor cursor = db.query("student", null, "number = ?", new String[] {"123456"}, null, null, null);

  

  到这里,我们可以看到update()、delete()、query()等方法中都传入了String[] whereArgs参数,这是一个字符串数组,也是判断条件,这可以帮助我们在同一个类目中搜索几类关键字的数据

  • 使用事务:事务的特性可以保证让某一系列的操作要么全部完成,要么一个都不会完成

SQLiteDatabase中包含两个方法控制事务:

开始事务:beginTransaction()

结束事务:endTransaction()

是否在事务中:inTransaction()

设置事务标志:setTransactionSuccessful()

  表示事物执行成功。如果程序在事务执行中调用该方法设置了事务成功则提交事务,否则程序将会回滚事务。

  注意:

  数据库查看,我们可以通过命令行方式进入SDK/platform-tools,输入adb shell,即可输入数据库的基本指令。但我觉得这种方式并不是很方便,我的做法是,登录SQLite Expert官方网站(http://www.sqliteexpert.com/download.html)下载一个SQLite Expert Personal 3,个人版的是免费的。然后就可以在Android Studio或者Eclipse中进如Android Monitor Device,在File Explorer中找到data/data/包名/database/*.db,点击导出,然后就可以用这个软件打开。

Android程序间数据内容提供器:

  上述三种方案是单个程序数据的存储,而我们在有些场景中,需要用到系统应用的数据,比如使用系统的通讯录、短信和媒体库等功能,那这就需要我们使用内容提供器(Content Provider),它可以用于在不同的应用程序之间实现数据共享。

一、获取其他应用的数据

  内容提供器是通过ContentResolver类来访问内容提供器中共享的数据,ContentResolver是由Context.getContentResolver() 得到的。

    Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder) ;

查询表

query()方法参数 对应SQL部分 描述
uri from table_name 指定查询的表明
projection where column = value 指定where的约束条件
selection - 为where中的占位符提供具体的值
selectionArgs group by column 指定需要group by的列
orderBy order by column1, column2 指定查询结果的排序方式

  讲到这里,我们会发现,内容提供器的查询方法跟数据库很类似,使用query()方法,不同的是,传进query()方法的参数有所区别。内容提供器传进query的值包含着URI,而URI记录着目标数据的地址,而数据库传进query的值包含着表名,因为数据库是对自身程序文件目录下进行的操作,所以并不需要定位,而内容提供器首先要定位到程序的包名,进而定位到数据文件夹,最终定位到表名,在URI中,我们可以看到最后一个斜杠后就是表名。

  • 内容URI

URI的标准格式

  content://com.example.app.provider/table 

URI的解析

  Uri uri = Uri.parse("content://com.example.app.provider/table") 

URI规则

    * 表示匹配任意长度的任意字符

    content://com.example.app.provider/*

    # 表示匹配任意长度的数字

    content://com.example.app.provider/table/#

二、提供应用自身的数据  

  • 内容提供器的六个方法

    1、onCreate()

      初始化内容提供器。完成数据库的创建和升级,只有在ContentResolver尝试访问程序数据才会被初始化

    2、query()

      查询数据。uri确定查哪张表,projection查询列,selection和selectionArgs查询哪些行

    3、insert()

      添加数据

    4、update()

      更新内容提供器已有的数据

    5、delete()

      删除数据

    6、getType()

      根据传入的内容URI来返回相应的MIME类型。

      一个内容URI对应的MIME字符串只要有三部分组成

        (1)必须以vnd开头  

        (2)以路径结尾,后接android.cursor.dir/,以id结尾,后接android.cursor.item/  

        (3)最后接上vnd.<authority>.<path>        

  • 匹配内容URI

    UriMatcher类

    addURI()方法,这个方法接受三个参数,分别把权限、路径和一个自定义代码传进去

    match()方法,将Uri对象传入,返回值是某个能够匹配这个Uri对象说对应的自定义代码

  内容提供类的核心是通过URI对象来定位数据的,但数据定位成功之后,那么就可以用类似于数据库操作的手段进行读取。如果想共享自身的数据,也可以通过URI对象,抛出自己的位置,等待其他程序定位到自身获取数据 

总结:   

存储方式 用途 特点
文件存储 存储一些简单的文本数据或二进制数据 不对存储的内容进行任何的格式化处理
SharedPreferences存储 存储boolean,int,float,long和String五种简单的数据类型,数据量小 方便,简洁,使用键值对的方式来存储数据,支持多种不同的数据类型存储,但不能条件查询
数据库存储 数据量大,且有条件 功能强大,条件查询,数据的增删改查,但使用较为复杂
内容提供器 跨程序之间的数据交换 通过URI对象来定位数据源

[1] 郭霖. 第一行代码 Android[J]. 2014.

[2] 大气象.Android四种存储方式.http://www.cnblogs.com/greatverve/archive/2011/12/27/android-sharedpreference-file-SQlite-contentprovider.html

Android Learning:数据存储方案归纳与总结的更多相关文章

  1. Android实现数据存储技术

    转载:Android实现数据存储技术 本文介绍Android中的5种数据存储方式. 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用Shar ...

  2. 关于Android开发数据存储的方式(一)

    关于Android开发数据存储方式(一) 在厦门做Android开发也有两个月了,快情人节了.我还在弄代码. 在微信平台上开发自己的APP,用到了数据存储的知识,如今总结一下: 整体的来讲.数据存储方 ...

  3. Android本地数据存储: ASimpleCache

    一:前言 在上一篇博客Android本地数据存储: Reservoir 博客中,我提到,除了Reservoir库,还可以采用ASimpleCache开源库,来实现本地数据存储.昨天并没有仔细的对比Re ...

  4. Android中数据存储(一)

    国庆没有给国家添堵,没有勾搭妹子,乖乖的写着自己的博客..... 本文将为大家介绍Android中数据存储的五种方式,数据存储可是非常重要的知识哦. 一,文件存储数据 ①在ROM存储数据 关于在ROM ...

  5. Android本地数据存储复习

    Android本地数据存储复习 Android无论是应用层还是系统层都需要在本地保存一些数据,尤其在应用层中使用的就更为普遍,大体有这么几种:SharedPreference,file,sqlite数 ...

  6. android学习笔记45——android的数据存储和IO

    android的数据存储和IO SharedPreferences与Editor简介 SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此其保存的数据主要是简单的类型的ke ...

  7. android中数据存储

    android中数据存储     Android 中存储数据的方式有五种:SQLite数据库.文件存储.内容提供者.网络.SharedPreferences(Key----value)五种存储方式. ...

  8. Sqlserver 高并发和大数据存储方案

    Sqlserver 高并发和大数据存储方案 随着用户的日益递增,日活和峰值的暴涨,数据库处理性能面临着巨大的挑战.下面分享下对实际10万+峰值的平台的数据库优化方案.与大家一起讨论,互相学习提高!   ...

  9. 前端数据存储方案集合(cookie localStorage等)以及详解 (二)

    前端数据存储方案集合(cookie localStorage等)以及详解 (二) 在之前的文章中已经介绍到了 前端存储方案中的 cookie . 但是 cookie 的存储上限是 4KB. 如果超过了 ...

随机推荐

  1. MyEclipse10搭建Strust2开发环境

    一.创建一个JavaWeb项目 启动MyEclipse10    ,然后在MyEclipse中创建一个JavaWeb项目,点击[File]---->[New]---->[WebProjec ...

  2. 闪回还原点(Flashback Restore Point)

    Flashback Restore Point(闪回还原点) 闪回还原点分两种,一种是Normal Restore Points(正常还原点),另一种是Guaranteed Restore Point ...

  3. mysql in 的两种使用方法

    简述MySQL 的in 的两种使用方法: 他们各自是在 in keyword后跟一张表(记录集).以及在in后面加上字符串集. 先讲后面跟着一张表的. 首先阐述三张表的结构: s(sno,sname. ...

  4. 用NodeJs实现延迟调用,规避定时任务的闭包问题

    很多人在用NodeJs的setTimeout(callback, delay[, arg][, ...])编写定时任务时,习惯上直接操作callback外部的对象object(闭包的特点).这样做有一 ...

  5. 关于weight属性使用的一些细节

    之前被这个属性困扰过好久,今天一个偶然的机会,终于把这个搞清楚了,现在与大家分享一下. 假设我们要在一个LinearLayout布局中显示两个按钮,button1和button2,button2的宽度 ...

  6. eclipse同时开两个tomcat

    首先设置环境变量: 接着修改其中一个tomcat下bin文件夹的startup.bat和catalina.bat 将里面所有CATALINA_HOME都修改为CATALINA_HOME2 然后 修改c ...

  7. PHP-popen()&nbsp;函数打开进程文件指针

    待更新 版权声明:本文为博主原创文章,未经博主允许不得转载.

  8. ui-router的使用

    使用时需要ui中用ui-view指令指定 如: <div ui-view></div> 首先配置注册 ui-route var mainModule = angular.mod ...

  9. (转)Spring读书笔记-----Spring的Bean之Bean的基本概念

    从前面我们知道Spring其实就是一个大型的工厂,而Spring容器中的Bean就是该工厂的产品.对于Spring容器能够生产那些产品,则取决于配置文件中配置. 对于我们而言,我们使用Spring框架 ...

  10. JAVA SE 框架之俄罗斯方块的效果

    Mygame package com.sun.c; import java.awt.event.KeyListener; import com.sun.v.MyJpanel; import com.s ...