在我们的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. 2018华南理工大学程序设计竞赛 H-对称与反对称

    H-对称与反对称 题目描述 给出一个N*N的方阵A.构造方阵B,C: 使得A = B + C.其中 B为对称矩阵,C为反对称矩阵. 对于方阵S中的任意元素,若(S)ij = (S)ji,则称S为对称矩 ...

  2. linux多线程学习笔记六--一次性初始化和线程私有数据【转】

    转自:http://blog.csdn.net/kkxgx/article/details/7513278 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,一次性初始化 以保证线程在调用资源 ...

  3. alloc_chrdev_region申请一个动态主设备号,并申请一系列次设备号

    ret = alloc_chrdev_region(&ndev, 0, 1, "chr_dev"); //分配设备号 alloc_chrdev_region申请一个动态主设 ...

  4. pip源配置

    1.使用配置文件配置文件[global]trusted-host=mirrors.aliyun.comindex-url=http://mirrors.aliyun.com/pypi/simple/ ...

  5. 记录: 百度webuploader 分片文件上传java服务器端(spring mvc)示例的优化

    最近项目上用到文件分片上传,于是找到了百度的一个开源前端控件webuploader. 于是尝试使用. 下载下来后,它提供的服务器端示例代码是php版的,那么Java版的呢? 其实,上传文件都是按照rf ...

  6. Integer.ParseInt()异常

    这里传参数:bookPage.nextPage,action接收到的是string型. 程序需要将string转成int来使用. 用上try { pageNUmber = Integer.parseI ...

  7. Codeforces Gym100735 D.Triangle Formation (KTU Programming Camp (Day 1) Lithuania, Birˇstonas, August 19, 2015)

    日常训练题解 D.Triangle Formation You are given N wooden sticks. Your task is to determine how many triang ...

  8. UVA 524 素数环 【dfs/回溯法】

    Description   A ring is composed of n (even number) circles as shown in diagram. Put natural numbers ...

  9. weblogic10.3.6忘记用户名或者密码的解决方法

    weblogic安装后,忘记访问控制台的用户名或者密码,可通过以下步骤来重置用户名密码. 版本:WebLogic Server 10.3 说明:%DOMAIN_HOME%:指WebLogic Serv ...

  10. CSS定位与布局:浮动

    浮动的特点   浮动(float)属性提出的作用是实现文字的环绕效果,一个元素浮动后,会脱离普通流.主要的特点如下: 浮动的元素会向左或者向右移动直到它的外边缘接触容器框(containing blo ...