Android 数据存储提供了四种存储方式:java
Shared Preferencesandroid
使用键值对(Map(key, value))来存储数据
Internal Storagesql
内部存储,存储在设备内存的 私人数据
External Storageshell
外部存储,存储在外部设备的 公共数据
SQLite Databases数据库
存储在关系型数据库;SQLite 是相似MySQL 的关系型数据库,由于其体较小,功能全,被运用在了大多嵌入式设备
Network Connectionapp
很是小的关系型数据库ide
import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; public class SimpleActivity extends Activity { private static final String INFO = "SimpleActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_layout); Log.i(INFO, INFO); SQLiteDatabase db = openOrCreateDatabase("simple.db", Context.MODE_PRIVATE, null); db.execSQL("DROP TABLE IF EXISTS Person"); // 建立表 db.execSQL("CREATE TABLE Person (" + " id INTEGER PRIMARY KEY AUTOINCREMENT," + " name varchar(30)," + " age SMALLINT" + ")"); Log.d(INFO, "Create Table Successful"); Person person = new Person(); person.name = "Tikitoo"; person.age = 23; // 插入数据 db.execSQL("INSERT INTO Person VALUES(NULL , ?, ?)", new Object[]{person.name, person.age}); Log.d(INFO, "Insert Successful"); person.name = "Davin"; person.age = 30; ContentValues cv = new ContentValues(); cv.put("name", person.name); cv.put("age", person.age); // 插入ContentValue 中的数据 db.insert("Person", null, cv); Log.d(INFO, "ContentValues Insert Successful"); cv = new ContentValues(); cv.put("age", 35); // 更新数据 db.update("Person", cv, "name = ?", new String[]{"Davin"}); Log.d(INFO, "Update Successful"); Cursor cursor = db.rawQuery("SELECT * FROM Person", null); while (cursor.moveToNext()) { int id = cursor.getInt(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); int age = cursor.getInt(cursor.getColumnIndex("age")); Log.d("INFO", id + name + age); } Log.d(INFO, "Query Successful"); cursor.close(); db.delete("Person", "age < ?", new String[]{"25"}); Log.d(INFO, "Delete Successful"); db.close(); // deleteDatabase("tikitoo_sqlite.db"); } }
参考:工具
Android SQLite Database Tutorial
Android中SQLite应用详解 - scott's blog - 博客频道 - CSDN.NETui
使用SQLite 调试工具ADB(adb)this
(android:adb环境变量的配置)[http://blog.csdn.net/huangbiao86/article/details/6664779]
使用ADB 工具查看adb shell
cd data,ls 出现错误,这是,输入su 回车便可,会请求访问权限,在手机赞成一下;
adb opendir failed ,permission denied
固然Android 对于SQLite 处理封装的对象 SQLiteOpenHelper 来返回 SQLiteDatabase 对象来实现增删改查
咱们再开发的时候,不能像上面写得那么简单,须要对封装一个子类,提供SQLiteOpenHelper 对象;
package com.tikitoo.android.sqlite.util; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Tikitoo1 on 2014/11/12. */ public class DBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "test.db"; private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { // 设置SQLiteDatabase.CursorFactory 为null super(context, DATABASE_NAME, null, DATABASE_VERSION); } // 数据库第一次建立被调用 @Override public void onCreate(SQLiteDatabase db) { // 初始化建立一个表 db.execSQL("CREATE TABLE IF NOT EXISTS Person" + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name varchar(30), age SMALLINT"); } // 若是数据库版本改变,则会调用 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 新增一个字段 db.execSQL("ALTER TABLE Person ADD COLUMN other STRING"); } }
DatabaseSQLite 对象实现对数据库的增删改查
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import java.util.ArrayList; import java.util.List; public class DBManager { private static final String INFO = DBManager.class.toString(); private DBHelper helper; private SQLiteDatabase db; public DBManager(Context context) { helper = new DBHelper(context); db = helper.getWritableDatabase(); // helper.getReadableDatabase(); } // 新增一条数据,将数据存在Person 对象,在放在List 集合中,遍历集合,能够实现多条数据插入; public void add(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(); } } // 更新一条数据,经过name 来修改age public void update(Person person) { ContentValues cv = new ContentValues(); cv.put("age", person.age); cv.put("info", person.info); // 参数,(表名, ContentValues 对象, where 条件,where 条件对应的值) db.update("Person",cv, "name = ?", new String[]{person.name}); } public void delete(Person person) { db.delete("Person", "age >= ?", new String[]{"" + person.age});// String.valueOf(person.age); } public List<Person> person() { List<Person> lists = new ArrayList<Person>(); // 使用rawQuery() 方法,返回游标对象,遍历出数据库的数据 Cursor cursor = db.rawQuery("SELECT * FROM Person", null); while (cursor.moveToNext()) { int _id = cursor.getInt(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); int age = cursor.getInt(cursor.getColumnIndex("age")); String info = cursor.getString(cursor.getColumnIndex("info")); Log.i(INFO, new Person(_id, name, age, info).toString()); } return lists; } // 关闭数据库 public void closeDB() { db.close(); } }
对了还有将数据表使用JavaBean 处理,将数据存储在Person 对象,比较方便
public class Person { public int _id; // id,惟一标识 public String name; // 姓名 public int age; // 年龄 public String info; // 备注信息 public Person() { } public Person(String name, int age, String info) { this.name = name; this.age = age; this.info = info; } public Person(int _id, String name, int age, String info) { this._id = _id; this.name = name; this.age = age; this.info = info; } // 重写toString() 方法 @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Person[ "); sb.append("name = " + this.name); // sb.append("; id = " + _id); sb.append("; age = " + this.age); sb.append("; info = " + this.info); sb.append(" ]"); return sb.toString(); } }
首先判断数据库实例是不是打开状态,
若是是,则打开一个可读写的数据库实例;
若是遇到磁盘已满,获取失败,再以可读模式打开数据库,返回数据库实例
若是不为空,已经打开,并非以只读模式打开的,
若是mDatabase 不为空则加锁,而后建立或打开新的数据库实例,比较版本,为数据库设置新的版本号,最后把不为空的mDatabase 解锁,把新建立的数据库实例赋值给 mDatabase,并返回新的实例;
因此,若是不遇到磁盘已满的状况下,两个方式返回的数据库实例是同样的,若是担忧这种方式发生,先调用 getWritableDatabase 方法, 若是异常,则在调用 getReadableDatabase ,固然这个时候的数据库实例是只读的