在我们的android实际开发过程,必不可少的一种行为操作对象就是数据。有些数据,对于用户而言是一次性的,这就要求我们每次进到App的时候,都需要去刷新数据。有些数据,对于用户而言又是具有一定时效性的,比如用户账号数据。这种情况下,就要求我们采用一定的数据保存措施,在这篇博客里面,我将为大家分享一些android里面常用的数据保存方法。

首先在android里面我们用的比较多的小数量存储方式可能就是SharedPreferences,那么什么是SharedPreferences呢?为了保存软件的设置参数,Android 平台为我们提供了一个SharedPreferences 类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences 保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs 目录下。说白了,它实际上也是一种文件存储方式。下面让我们来看看它的具体用法:

public static void openSharep(Context context,String name){
SharedPreferences sharedPreferences=context.getSharedPreferences(name,Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit(); editor.putString("name","hello");
editor.commit(); }

上面是将一个字符串,通过键值对的方式存储到xml文件里面。这个时候,你也许会问:在什么情况下,会将SharedPreferences里面的数据删掉呢?当我们卸载app的时候,SharePreferences是否还在呢?当我的应用程序更新的时候,SharePreferences文件是否还在呢?我想这有可能跟你当前所使用android系统版本有关系,本人也没有细查这个问题,如有不对还请留言讨论。通过上面的代码你可能就能够发现,SharePreferences里面保存的数据还是相当有限的,主要是一些标识类的数据。

那么如果你需要在项目里面保存大量的数据,你会怎么办呢?其实常用的有两种方式:一种是文件存储;另外一种就是sqlite数据库;文件储存的方式,我们就不做过多的解释了,直接上代码,大家肯定就能够明白了。

String fileName = etFileName.getText().toString();
String fileContent = etFileContent.getText().toString();
FileOutputStream out = null;
try {
out = context.openFileOutput(fileName, Context.MODE_PRIVATE);
out.write(fileContent.getBytes("UTF-8"));
Toast.makeText(this,"保存成功",Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
out.close();
}catch (Exception e){
e.printStackTrace();
}
}

上面的代码我们直接定义一个输出流就可以将我们希望保存的信息写入文件系统里面了。然后我们再来看看读取流的代码:

String fileName=etFileName.getText().toString();
FileInputStream in=null;
ByteArrayOutputStream bout=null;
byte[] buf=new byte[1024];
bout=new ByteArrayOutputStream();
int length=0;
try{
in=context.openFileInput(fileName);
while((length=in.read(buf))!=-1){
bout.write(buf,0,length);
}
byte[] content = bout.toByteArray();
tvInfo.setText(new String(content,"UTF-8")); //设置文本框为读取的内容
}catch (Exception e){
e.printStackTrace();
}
tvInfo.invalidate(); //刷新屏幕
try{
in.close();
bout.close();
}
catch(Exception e){}

通过上面的文件操作代码,我们可以很直观的发现文件系统无非就是一些中规中矩的文件读写操作了。接下来,我们将重点看看数据保存的最重要角色sqlite数据库。通过数据库保存下来的文件,我们都知道相对于普通的文件系统具有更好的结构性。就是说我们在操作数据的时候,可以更加有条理性的进行。

首先让我们来看看android里面应该怎样定义一个数据库操作对象呢?其实很简单,我们只需要定义一个类,然后让它继承SQLiteOpenHelper就可以了。请看测试类定义:

public class SqliteTest extends SQLiteOpenHelper {

    public SqliteTest(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) { } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

通过上面的类定义我们可以看到,当我们实现一个构造方法、onCreate、onUpgrade方法之后,我们具有一个数据库操作的对象了。接下来让我们首先来完善一下上面SqliteTest类,提供完整的代码实现:

public class SqliteTest extends SQLiteOpenHelper {

    private static final int VERSION = 1;
private static final String DB_NAME = "test.db"; public SqliteTest(Context context) {
super(context, DB_NAME, null, VERSION);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS person" +
"(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, info TEXT)");
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTER TABLE person ADD COLUMN other STRING");
}
}

然后当我们拿到这个数据库操作的对象之后,就应该考虑怎样使用这个对象了?比如我现在想要往这个数据库里面插入一些数据,请看下面的测试代码:

private SQLiteDatabase db;
private SqliteTest helper; private void getSqliteDb(){
db=helper.getWritableDatabase();
} private void addData(List<Person> persons){
db.beginTransaction(); //开始事务
try {
for (Person person : persons) {
db.execSQL("INSERT INTO person VALUES(null, ?, ?, ?)", new Object[]{person.name, person.age, person.info});
}
db.setTransactionSuccessful(); //设置事务成功完成
} finally {
db.endTransaction(); //结束事务
}
}

通过上面的代码我就可以实现数据的插入操作了。

在这篇博客的最后,让我们来看看SQLiteOpenHelper类的源码,探索一下为什么实现该类之后就能够进行数据库操作了呢?我们可以先来看看如下方法:

public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}

当我们调用getWriteableDatabase方法之后,程序会同步的调用getDatabaseLocked方法:

private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
// The database is already open for business.
return mDatabase;
}
} if (mIsInitializing) {
throw new IllegalStateException("getDatabase called recursively");
} SQLiteDatabase db = mDatabase;
try {
mIsInitializing = true; if (db != null) {
if (writable && db.isReadOnly()) {
db.reopenReadWrite();
}
} else if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
try {
if (DEBUG_STRICT_READONLY && !writable) {
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
} else {
db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
mFactory, mErrorHandler);
}
} catch (SQLiteException ex) {
if (writable) {
throw ex;
}
Log.e(TAG, "Couldn't open " + mName
+ " for writing (will try read-only):", ex);
final String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory,
SQLiteDatabase.OPEN_READONLY, mErrorHandler);
}
} onConfigure(db); final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
} db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
} onOpen(db); if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
} mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}

调用这个方法之后系统就能够给我们提供一个SQLiteDatabase对象,然后我们就可以利用SQLiteDatabase利用的方法进行数据库操作了。

至于SQLiteDatabase层的源码,我自己还没有怎么研究过,如有什么不对的地方,欢迎拍砖!

android开发系列之数据存储的更多相关文章

  1. Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用

    前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...

  2. Android开发笔记之: 数据存储方式详解

    无论是神马平台,神马开发环境,神马软件程序,数据都是核心.对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用.总体的来讲,数据存储方式有三种:一个是文件,一个是数 ...

  3. Android开发-API指南-数据存储

    Storage Options 英文原文:http://developer.android.com/guide/topics/data/data-storage.html 采集日期:2015-02-0 ...

  4. Android开发手记(18) 数据存储三 SQLite存储数据

    Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SQLite 是以嵌入式为目的 ...

  5. Android开发手记(17) 数据存储二 文件存储数据

    Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 本文主要介绍如何使用文件来存储 ...

  6. Android开发手记(20) 数据存储五 网络存储

    Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 安卓的网络存储比较简单,因为A ...

  7. Android开发手记(19) 数据存储四 ContentProvider

    转载自:http://www.cnblogs.com/devinzhang/archive/2012/01/20/2327863.html Android为数据存储提供了五种方式: 1.SharedP ...

  8. Android开发手记(16) 数据存储一 SharedPreferences

    Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SharedPreferenc ...

  9. Android 开发系列教程之(一)Android基础知识

    什么是Android Android一词最早是出现在法国作家维里耶德利尔·亚当1986年发表的<未来夏娃>这部科幻小说中,作者利尔·亚当将外表像人类的机器起名为Android,这就是And ...

随机推荐

  1. nodeJS学习(8)--- WS/...开发 NodeJS 项目-节3 <使用 mongodb 完整实例过程>

    使用 mongodb 的小系统 参考:https://my.oschina.net/chenhao901007/blog/312367 1. Robomongo 创建项目的数据库和数据表 参考:htt ...

  2. 访问外网 ML2 的配置

    通过 router 可以实现位于不同 vlan 中的 instance 之间的通信. 接下来要探讨的问题是 instance 如何与外部网络通信. 这里的外部网络是指的租户网络以外的网络. 租户网络是 ...

  3. POJ1927 Area in Triangle

      Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1458   Accepted: 759 Description Give ...

  4. IHTMLDocument2的所有成员、属性、方法、事件[转]

    原文发布时间为:2010-07-01 -- 来源于本人的百度文章 [由搬家工具导入] IHTMLDocument2 InterfaceGets information about the docume ...

  5. VS Code开发技巧集锦【转】

    转自:http://blog.csdn.net/tiantangyouzui/article/details/52163175 入门 自定义 扩展 文件/文件夹管理 编辑技巧 智能感应功能 代码片段 ...

  6. android的动态代码

    1,Android代码设置Shape,corners,Gradient  (http://blog.csdn.net/houshunwei/article/details/17392409) int ...

  7. Linux中查看某个软件的安装路径

    Linux中查看某个软件的安装路径(地址)有时显得非常重要.比如某个文件的快速启动项被删除,或者你要建立快速启动项,或者想删除.添加安装文件等等,很多地方都要用到查案文件安装路径的命令. 这里给大家介 ...

  8. Codeforces Round #343 (Div. 2) A. Far Relative’s Birthday Cake【暴力/组合数】

    A. Far Relative’s Birthday Cake time limit per test 1 second memory limit per test 256 megabytes inp ...

  9. dubbo框架的简单介绍

    以下的官网的介绍. dubbo是SOA.小例子是简单的远程调用(生产者消费者的模式出现).http://blog.csdn.net/huangyekan/article/details/4217267 ...

  10. Java IO设计模式

    JAVA IO 设计模式彻底分析 2011-01-06 14:20:09|  分类: java|字号 订阅 http://blog.csdn.net/tianyue168/archive/2010/0 ...