Android数据存储

数据存储

Android数据存储的几种形式

  1. Internal Storage Store private data on the device memory. 通过mContext.getFilesDir()来得到data/data/包名/File目录
  2. External Storage Store public data on the shared external storage.
TextView tv = (TextView) findViewById(R.id.tv_sdsize);
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
long sizeAvailSize = blockSize * availableBlocks;
String str = Formatter.formatFileSize(this, sizeAvailSize);
tv.setText(str);
  1. SharedPreferences Store private primitive data in key-value pairs. 会在data/data/包名/shared_prefes里面去创建相应的xml文件,根节点是Map,其实内部就是将数据保存到Map集合中, 然后将该集合中的数据写到xml文件中进行保存。
<map>
	<string name="password">123</string>
	<boolean name="isLogin" value="false"/>
</map>
//获取系统的一个sharedpreference文件  名字叫sp
SharedPreferences sp = context.getSharedPreferences("sp", Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
//创建一个编辑器 可以编辑 sp
Editor editor = sp.edit();
editor.putString("name", name);
editor.putString("password", password);
editor.putBoolean("boolean", false);
editor.putInt("int", 8888);
editor.putFloat("float",3.14159f);
//注意:调用 commit 提交 数据到文件.
editor.commit();
//editor.clear();
  1. SQLiteDatabase Store structured data in a private database. Android平台中嵌入了一个关系型数据库SQLite,和其他数据库不同的是SQLite存储数据时不区分类型,例如一个字段声明为Integer类型, 我们也可以将一个字符串存入, 一个字段声明为布尔型,我们也可以存入浮点数。除非是主键被定义为Integer,这时只能存储64位整数创建数据库的表时可以不指定数据类型,例如:
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20))  
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name)

`SQLite`支持大部分标准`SQL`语句,增删改查语句都是通用的,分页查询语句和`MySQL`相同

SELECT * FROM person LIMIT 20 OFFSET 10       
SELECT * FROM person LIMIT 10,20    
SELECT * FROM reading_history ORDER BY _id DESC LIMIT 3, 4
DELETE FROM test WHERE _id IN (SELECT _id FROM test ORDER BY _id DESC LIMIT 3, 20)

`SQLite`数据库的使用 - 继承`SQLiteOpenHelper`

public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
					
	/**
	 * name 数据库的名称 cursorfactory 游标工厂 一般设置null 默认游标工厂 version 数据库的版本
	 * 版本号从1开始的
	 * 
	 * @param context
	 */
	public NoteSQLiteOpenHelper(Context context) {
		super(context, "note.db", null, 1);
	}
	/**
	 * oncreate 方法 会在数据库第一创建的时候的是被调用 适合做数据库表结构的初始化
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table account (id integer primary key autoincrement , name  varchar(20), money varchar(20) )");
	}
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
		db.execSQL("DROP TABLE IF EXISTS " + account);
		this.onCreate(db);
	}
}

- 获取

public class NoteDao {
	private NoteSQLiteOpenHelper helper;
	public NoteDao(Context context) {
		helper = new NoteSQLiteOpenHelper(context);
	}
	/**
	 * 添加一条账目信息 到数据库
	 * 
	 * @param name
	 *            花销的名称
	 * @param money
	 *            金额
	 */
	public void add(String name, float money) {
		SQLiteDatabase db = helper.getWritableDatabase();
		db.execSQL("insert into account (name,money) values (?,?)",
				new Object[] { name, money });
		// 记住 关闭.
		db.close();
	}
	public void delete(int id) {
		SQLiteDatabase db = helper.getWritableDatabase();
		db.execSQL("delete from account where id=?", new Object[] { id });
		db.close();
	}
	public void update(int id, float newmoney) {
		SQLiteDatabase db = helper.getWritableDatabase();
		db.execSQL("update account set money =? where id=?", new Object[] {
				newmoney, id });
		db.close();
	}
	/**
	 * 返回数据库所有的条目
	 * 
	 * @return
	 */
	public List<NoteBean> findAll() {
		// 得到可读的数据库
		SQLiteDatabase db = helper.getReadableDatabase();
		List<NoteBean> noteBeans = new ArrayList<NoteBean>();
		// 获取到数据库查询的结果游标
		Cursor cursor = db.rawQuery("select id,money,name from account ", null);
		while (cursor.moveToNext()) {
			int id = cursor.getInt(cursor.getColumnIndex("id"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			float money = cursor.getFloat(cursor.getColumnIndex("money"));
			NoteBean bean = new NoteBean(id, money, name);
			noteBeans.add(bean);
			bean = null;
		}
		db.close();
		return noteBeans;
	}
	/**
	 * 模拟一个转账的操作. 使用数据库的事务
	 * 
	 * @throws Exception
	 */
	public void testTransaction() throws Exception {
		// 得到可写的数据库
		SQLiteDatabase db = helper.getWritableDatabase();
		db.beginTransaction(); // 开始事务
		try {
			db.execSQL("update account set money = money - 5 where id=? ",
					new String[] { "2" });
			db.execSQL("update account set money = money + 5 where id=? ",
					new String[] { "3" });
			db.setTransactionSuccessful();
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			db.endTransaction();//关闭事务.
			db.close();
		}
	}
}
public class NoteDao2 {
	private NoteSQLiteOpenHelper helper;
	public NoteDao2(Context context) {
		helper = new NoteSQLiteOpenHelper(context);
	}
	/**
	 * 添加一条账目信息 到数据库
	 * 
	 * @param name
	 *            花销的名称
	 * @param money
	 *            金额
	 * 
	 * @return true 插入成功 false 失败
	 */
	public boolean add(String name, float money) {
		SQLiteDatabase db = helper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("name", name);
		values.put("money", money);
		long rawid = db.insert("account", null, values);
		db.close();
		if (rawid > 0) {
			return true;
		} else {
			return false;
		}
	}
	public boolean delete(int id) {
		SQLiteDatabase db = helper.getWritableDatabase();
		int result = db.delete("account", "id=?", new String[] { id + "" });
		db.close();
		if (result > 0) {
			return true;
		} else {
			return false;
		}
	}
	public boolean update(int id, float newmoney) {
		SQLiteDatabase db = helper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("id", id);
		values.put("money", newmoney);
		int result = db.update("account", values, "id=?", new String[] { id
				+ "" });
		db.close();
		if (result > 0) {
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 返回数据库所有的条目
	 * 
	 * @return
	 */
	public List<NoteBean> findAll() {
		// 得到可读的数据库
		SQLiteDatabase db = helper.getReadableDatabase();
		List<NoteBean> noteBeans = new ArrayList<NoteBean>();
		Cursor cursor = db.query("account", new String[] { "id", "name",
				"money" }, null, null, null, null, null);
		while (cursor.moveToNext()) {
			int id = cursor.getInt(cursor.getColumnIndex("id"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			float money = cursor.getFloat(cursor.getColumnIndex("money"));
			NoteBean bean = new NoteBean(id, money, name);
			noteBeans.add(bean);
			bean = null;
		}
		db.close();
		return noteBeans;
	}
}
  1. Network Store data on the web with your own network server.
  2. /data/data/包名下的apk在安装时提示解析失败。 我们在更新或安装apk时一般将其放到外部存储设备中来进行安装,但是如果一个手机没有外部存储设备该怎么办呢?总不能就不给更新或者安装了。 可能你会觉得很简单啊,我用mContext.getCacheDir()或者mContext.getFilesDir()等获取内部路径,把apk放到这里面进行安装,但是你会发现安装 不了,提示解析失败。 这是为什么呢?其实是权限的问题。安装应用的app是没有权限获取你应用的内部存储文件的,所以才会安装不上,那该怎么解决呢? 答案就是修改权限。
try {
	InputStream is = getAssets().open(fileName);
	File file;
	if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
		file = new File(Environment.getExternalStorageDirectory()
				+ File.separator + fileName);
	} else {
		file = new File(mContext.getFilesDir()
				+ File.separator + fileName);
		String cmd = "chmod 777 " + file.getPath();
		try {
			Runtime.getRuntime().exec(cmd);
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
	}
	file.createNewFile();
	FileOutputStream fos = new FileOutputStream(file);
	byte[] temp = new byte[1024];
	int i = 0;
	while ((i = is.read(temp)) > 0) {
		fos.write(temp, 0, i);
	}
	fos.close();
	is.close();
	Intent intent = new Intent(Intent.ACTION_VIEW);
	intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	intent.setDataAndType(Uri.parse("file://" + file),
			"application/vnd.android.package-archive");
	startActivity(intent);
} catch (Exception e) {
	LogUtil.e("@@@", e.toString());
	e.printStackTrace();
}

3. 清除缓存&清除数据

清除数据会清除/data/data/包名中的所有文件

清楚缓存会清楚getCacheDir()目录下的内容,也就是/data/data/<当前应用程序包名>/cache/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏.NET开发者社区

一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)

在本系列第一篇《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](一)》中,我为大家介绍...

29110
来自专栏解Bug之路

MySql之自动生成CRUD代码

MyBatis能够通过获取MySql中的information_schema从而获取表的字段等信息,最后通过这些信息生成代码。 笔者受此启发,将MyBatis...

1113
来自专栏Android 研究

APK安装流程详解10——PackageParser解析APK(下)

其中第一个parseBaseApk(File, AssetManager, int)方法,已经讲解过了,请参考APK安装流程详解9——PackageParser...

2371
来自专栏jeremy的技术点滴

通过WebSocket传输文件

3.1K5
来自专栏MasiMaro 的技术博文

windows 下文件的高级操作

本文主要说明在Windows下操作文件的高级方法,比如直接读写磁盘,文件的异步操作,而文件普通的读写方式在网上可以找到一大堆资料,在这也就不再进行专门的说明。

2283
来自专栏Android干货

安卓开发_数据存储技术_sqlite

2907
来自专栏编程思想之路

Android中ContentProvider简介

翻看Android源码可以发现,Android一般的代码架构如下:activity,service,receiver----contentProvider---...

2116
来自专栏菩提树下的杨过

Spring Security笔记:登录尝试次数限制

今天在前面一节的基础之上,再增加一点新内容,默认情况下Spring Security不会对登录错误的尝试次数做限制,也就是说允许暴力尝试,这显然不够安全,下面的...

4405
来自专栏Python小屋

Python列表模拟页面调度LRU算法(京东2016笔试题)

问题描述:一进程刚获得3个主存块的使用权,若该进程访问页面的次序是1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5。当采用LRU算法时,发生...

3575
来自专栏【转载】DRF+Vue+Mysql_生鲜超市系统

五、商品列表页

在goods文件夹下面新建view_base.py,为了区分django和django rest framework的view

1960

扫码关注云+社区

领取腾讯云代金券