android开发系列之数据存储
在我们的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开发系列之数据存储的更多相关文章
- Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...
- Android开发笔记之: 数据存储方式详解
无论是神马平台,神马开发环境,神马软件程序,数据都是核心.对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用.总体的来讲,数据存储方式有三种:一个是文件,一个是数 ...
- Android开发-API指南-数据存储
Storage Options 英文原文:http://developer.android.com/guide/topics/data/data-storage.html 采集日期:2015-02-0 ...
- Android开发手记(18) 数据存储三 SQLite存储数据
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SQLite 是以嵌入式为目的 ...
- Android开发手记(17) 数据存储二 文件存储数据
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 本文主要介绍如何使用文件来存储 ...
- Android开发手记(20) 数据存储五 网络存储
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 安卓的网络存储比较简单,因为A ...
- Android开发手记(19) 数据存储四 ContentProvider
转载自:http://www.cnblogs.com/devinzhang/archive/2012/01/20/2327863.html Android为数据存储提供了五种方式: 1.SharedP ...
- Android开发手记(16) 数据存储一 SharedPreferences
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SharedPreferenc ...
- Android 开发系列教程之(一)Android基础知识
什么是Android Android一词最早是出现在法国作家维里耶德利尔·亚当1986年发表的<未来夏娃>这部科幻小说中,作者利尔·亚当将外表像人类的机器起名为Android,这就是And ...
随机推荐
- mvc3 学习链接收集
原文发布时间为:2011-04-17 -- 来源于本人的百度文章 [由搬家工具导入] The mvc3 study links collection http://dotnetslackers.com ...
- .NET抓取数据范例 抓取页面上所有的链接
原文发布时间为:2009-11-15 -- 来源于本人的百度文章 [由搬家工具导入] .NET抓取数据范例 抓取页面上所有的链接 前台: <%@ Page Language="C#&q ...
- Chrome 75 将原生支持图片懒加载
4 月 6 日,Google 的 Chrome & Web 平台工程经理 Addy Osmani 在个人博客发文,介绍到 <img> 和 <iframe> 的 load ...
- 牛客网 牛客小白月赛2 D.虚虚实实-无向图判欧拉路径
D.虚虚实实 链接:https://www.nowcoder.com/acm/contest/86/D 这个题是无向图判欧拉路径,首先要判是否连通,然后再判欧拉路径就可以,板子题. 板子来源: ...
- 2018年东北农业大学春季校赛 E 阶乘后的0【数论】
链接:https://www.nowcoder.com/acm/contest/93/E来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- HDU 1568 Fibonacci【求斐波那契数的前4位/递推式】
Fibonacci Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Proble ...
- Codeforces 546D Soldier and Number Game(数论)
类似筛素数的方法……求出前缀和.然后直接O(1)回答即可. #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) ...
- koa2 从入门到进阶之路 (三)
之前的文章我们介绍了一下 koa 路由,get 传值,动态路由,本节我们看一下 koa 中间件 以及 koa 中间件的洋葱图执行流程. 一.什么是 Koa 的中间件 通俗的讲:中间件就是匹配路由之前或 ...
- PHP message: PHP Fatal error: require(): Failed opening required
PHP message: PHP Warning: require(/data/wwwroot/blog.sgfoot.com/bootstrap/autoload.php): failed to o ...
- 一次lenovo a390t刷机体验
今天一朋友说自己的联想a390t手机有时候打着打着电话就没声音了,手机好像死机了一样,以前用着挺好的没什么毛病. 因为以前用刷机精灵刷过几个android手机,感觉挺简单的,只要找好对应的rom点击两 ...