DataFramework是Android的SQLite数据库框架,在程序中,可以通过编写一个xml文件创建,修改,删除数据库记录!项目如图:
项目不包含demo就7个目标文件,源码分析如下:
public class DataFramework { // 操作类,主要是操作成员DataFrameworkCore的
public class Entity { //实体类收集的信息从数据库中的记录
public class EntityCursor implements Cursor, Iterable<Entity> { //实例每行的集合
public abstract class EntityEditActivity extends Activity // 界面操作基础类
public class DataFrameworkCore { // 核心 操作数据库的封装
public class Field { //字段的封装
public class Table { //表的封装
核心源码如下:
public class DataFrameworkCore { // 核心 操作数据库的封装
private final static int TYPESQL_INSERT = 0;
private final static int TYPESQL_UPDATE = 1;
private final static int TYPESQL_DELETE = 2;
private String mPackage = "";
private ArrayList<String> mLanguages = new ArrayList<String>();
private String mCurrentLanguage;
private SQLiteDatabase mDb;
private DatabaseHelper mDbHelper;
private ArrayList<Table> mTables; // 表的操作
private String mDataBaseName = "";
private int mDataBaseOldVersion = 0;
private int mDataBaseVersion = 0;
private Context mCtx;
private boolean mSaveInitialValues = false;
/**
* Constructor
*/
public DataFrameworkCore() {
}
private class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper() {
super(mCtx, mDataBaseName, null, mDataBaseVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
System.out.println("(onCreate) CREATE TABLES");
mDataBaseOldVersion = 0;
ArrayList<Table> tables = mTables;
int tableCount = tables.size();
for (int i = 0; i < tableCount; i++)
db.execSQL(tables.get(i).getSQLCreateTable());
mSaveInitialValues = true;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w("TableDB", "Upgrading database from version " + oldVersion
+ " to " + newVersion);
mDataBaseOldVersion = oldVersion;
ArrayList<Table> tables = mTables;
int tableCount = tables.size();
for (int i = 0; i < tableCount; i++) {
Table t = tables.get(i);
if (add(t.getNewInVersion(), oldVersion, newVersion)) {
System.out.println("(onUpgrade) CREATE TABLE: "
+ t.getName());
db.execSQL(t.getSQLCreateTable());
} else {
ArrayList<Field> fields = t.getFields();
int fieldCount = fields.size();
for (int j = 0; j < fieldCount; j++) {
Field f = fields.get(j);
if (add(f.getNewInVersion(), oldVersion, newVersion)) {
String sql = t.getSQLAddField(f);
if (sql != null) {
System.out
.println("(onUpgrade) ADD FIELD: "
+ t.getName() + "("
+ f.getName() + ")");
db.execSQL(sql);
}
}
}
}
}
mSaveInitialValues = true;
}
private boolean add(int version, int oldVersion, int newVersion) {
if (version > oldVersion && version <= newVersion)
return true;
else
return false;
}
}
public void open(Context context, String namePackage,
ArrayList<Table> tables) throws XmlPullParserException, IOException { // 打开一个数据库
try {
if (tables.size() == 0) {
mPackage = namePackage;
mTables = tables;
mCtx = context;
int idTables = context.getResources().getIdentifier(
namePackage + ":xml/tables", null, null);
if (idTables != 0) {
XmlResourceParser x = mCtx.getResources().getXml(idTables);
int eventType = x.getEventType();
Table currentTable = new Table("");
Field currentField = new Field("");
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (x.getName().equals("database")) {
mDataBaseName = x.getAttributeValue(null,
"name");
mDataBaseVersion = Integer.parseInt(x
.getAttributeValue(null, "version"));
if (x.getAttributeValue(null, "languages") != null) {
boolean isFirst = true;
StringTokenizer tokens = new StringTokenizer(
x.getAttributeValue(null,
"languages"), "|");
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken();
mLanguages.add(token);
if (isFirst) {
mCurrentLanguage = token;
isFirst = false;
}
if (Locale.getDefault().getLanguage()
.equals(token))
mCurrentLanguage = token;
}
System.out
.println("Lenguaje por defecto usado en la base de datos: "
+ mCurrentLanguage);
}
} else if (x.getName().equals("table")) {
currentTable = new Table(x.getAttributeValue(
null, "name"));
if (x.getAttributeValue(null, "to-string") != null)
currentTable.setToString(x
.getAttributeValue(null,
"to-string"));
if (x.getAttributeValue(null, "backup") != null) {
if (x.getAttributeValue(null, "backup")
.equals("no"))
currentTable.setBackup(false);
}
if (x.getAttributeValue(null, "new-in-version") != null) {
currentTable.setNewInVersion(Integer
.parseInt(x.getAttributeValue(null,
"new-in-version")));
}
} else if (x.getName().equals("field")) {
currentField = new Field(x.getAttributeValue(
null, "name"));
if (x.getAttributeValue(null, "type") != null)
currentField.setType(x.getAttributeValue(
null, "type"));
if (x.getAttributeValue(null, "foreign-table") != null)
currentField.setForeignTable(x
.getAttributeValue(null,
"foreign-table"));
if (x.getAttributeValue(null, "obligatory") != null) {
if (x.getAttributeValue(null, "obligatory") == "true")
currentField.setObligatory(true);
}
if (x.getAttributeValue(null, "size") != null)
currentField.setSize(Integer.parseInt(x
.getAttributeValue(null, "size")));
if (x.getAttributeValue(null, "default") != null)
currentField
.setTextDefault(x
.getAttributeValue(null,
"default"));
if (x.getAttributeValue(null, "new-in-version") != null) {
currentField.setNewInVersion(Integer
.parseInt(x.getAttributeValue(null,
"new-in-version")));
}
currentTable.addField(currentField);
}
}
if (eventType == XmlPullParser.END_TAG) {
if (x.getName().equals("table")) {
tables.add(currentTable);
}
}
eventType = x.next();
}
x.close();
} else {
System.out
.println("=========================================");
System.out
.println("No se ha encontrado el archivo tables.xml");
System.out
.println("=========================================");
}
}
mSaveInitialValues = false;
mDbHelper = new DatabaseHelper();
mDb = mDbHelper.getWritableDatabase();
if (mSaveInitialValues)
saveInitialValues();
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() { // 关闭
mDbHelper.close();
}
public void saveInitialValues() throws XmlPullParserException, IOException { // 插入一条数据
try {
for (int i = mDataBaseOldVersion + 1; i <= mDataBaseVersion; i++) {
int idInitialValues = mCtx.getResources().getIdentifier(
mPackage + ":xml/initialvalues_v" + i, null, null);
if (idInitialValues != 0) {
XmlResourceParser x = mCtx.getResources().getXml(
idInitialValues);
insertXML(x);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void backup(String file) throws XmlPullParserException, IOException { //备份
backup(file, false);
}
public void backup(String file, boolean forceBackup)
throws XmlPullParserException, IOException { // 备份
File f = new File(file);
if (f.exists())
f.delete();
FileOutputStream fOut = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<values>\n");
List<Table> tables = mTables;
int tableCount = tables.size();
System.out.println("tablas: " + tables.size());
for (int i = 0; i < tableCount; i++) {
Table t = tables.get(i);
if (t.isBackup() || forceBackup) {
String tableName = t.getName();
System.out.println("tabla: " + tableName);
String[] aux = t.getFieldsToArray();
Cursor c = getDB().query(tableName, aux, null, null, null,
null, null);
c.moveToFirst();
ArrayList<Field> fields = t.getFields();
int fieldCount = fields.size();
while (!c.isAfterLast()) {
osw.append("<row table=\""
+ tableName
+ "\" id=\""
+ c.getString(c
.getColumnIndex(DataFramework.KEY_ID))
+ "\">\n");
for (int j = 0; j < fieldCount; j++) {
Field field = fields.get(j);
if (c.getString(c.getColumnIndex(field.getName())) != null)
osw.append("<field name=\""
+ field.getName()
+ "\" value=\""
+ c.getString(
c.getColumnIndex(field.getName()))
.replace("\"", """)
+ "\" />\n");
}
osw.append("</row>\n");
c.moveToNext();
}
c.close();
}
}
osw.append("</values>\n");
osw.flush();
osw.close();
}
public void restore(String file) throws XmlPullParserException, IOException {
try { // 还原
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser x = (XmlPullParser) factory.newPullParser();
x.setInput(new FileReader(file));
insertXML(x);
} catch (IOException e) {
e.printStackTrace();
}
}
private void insertXML(XmlPullParser x) throws XmlPullParserException,
IOException { // 根据xml的规则插入数据
try {
int eventType = x.getEventType();
Entity currenEntity = null;
int typesql = TYPESQL_INSERT;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (x.getName().equals("row")) {
currenEntity = null;
if (x.getAttributeValue(null, "table") != null) {
long id = -1;
if (x.getAttributeValue(null, "action") != null) {
if (x.getAttributeValue(null, "action").equals(
"update")) {
typesql = TYPESQL_UPDATE;
} else if (x.getAttributeValue(null, "action")
.equals("delete")) {
typesql = TYPESQL_DELETE;
} else {
typesql = TYPESQL_INSERT;
}
} else {
typesql = TYPESQL_INSERT;
}
if (x.getAttributeValue(null, "id") != null) {
id = Long.parseLong(x.getAttributeValue(null,
"id"));
}
if (typesql == TYPESQL_INSERT) {
currenEntity = new Entity(x.getAttributeValue(
null, "table"));
if (id > 0)
currenEntity.setForceId(id);
} else if (typesql == TYPESQL_UPDATE) {
if (id > 0)
currenEntity = new Entity(
x.getAttributeValue(null, "table"),
id);
} else {
if (id > 0)
currenEntity = new Entity(
x.getAttributeValue(null, "table"),
id);
}
}
}
if (x.getName().equals("field")) {
if (x.getAttributeValue(null, "lang") != null) {
if ((x.getAttributeValue(null, "name") != null)
&& (x.getAttributeValue(null, "value") != null)) {
if (currenEntity != null)
currenEntity.setMultilanguageValue(
x.getAttributeValue(null, "name"),
x.getAttributeValue(null, "lang"),
x.getAttributeValue(null, "value"));
}
} else {
if ((x.getAttributeValue(null, "name") != null)
&& (x.getAttributeValue(null, "value") != null)) {
if (currenEntity != null) {
if (x.getAttributeValue(null, "value") != null) {
currenEntity.setValue(
x.getAttributeValue(null,
"name"),
x.getAttributeValue(null,
"value").replace(
""", "\""));
}
}
}
}
}
}
if (eventType == XmlPullParser.END_TAG) {
if (x.getName().equals("row")) {
if (currenEntity != null) {
if (typesql == TYPESQL_DELETE) {
currenEntity.delete();
} else {
currenEntity.save();
}
}
}
}
eventType = x.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public SQLiteDatabase getDB() { // 获得数据库
return mDb;
}
public Context getContext() { // 获得句柄
return mCtx;
}
public String getPackage() { // 获取包
return mPackage;
}
public void setForceLanguage(String lang) { //
if (mLanguages.contains(lang))
mCurrentLanguage = lang;
}
public ArrayList<String> getLanguages() { // 获取支持的语言组
return mLanguages;
}
public String getCurrentLanguage() { // 获得当前语言
return mCurrentLanguage;
}
}
如何使用它们呢?它们有什么规范吗?
xml的规范如下,分别有database、tables、field、表值!
tables.xml 规范
demo1:
<database name="notes_db" version="1">
<table name="notes" to-string="%title%">
<field name="title" obligatory="true" type="text" size="128"/>
<field name="body" obligatory="true" type="text"/>
<field name="category_id" type="foreign-key" foreign-table="categories" />
</table>
<table name="categories" to-string="%name%">
<field name="name" obligatory="true" type="name" size="128"/>
</table>
</database>
demo2:
<database name="notes_db" version="2">
<table name="notes" to-string="%title%">
<field name="title" obligatory="true" type="text" size="128"/>
<field name="body" obligatory="true" type="text"/>
<field name="category_id" type="foreign-key" foreign-table="categories" />
<field name="importance_id" type="foreign-key" foreign-table="importance" new-in-
version="2" />
</table>
<table name="categories" to-string="%name%">
<field name="name" obligatory="true" type="name" size="128"/>
</table>
<table name="importance" to-string="%name%" new-in-version="2">
<field name="name" obligatory="true" type="name" size="128"/>
</table>
</database>
字段以及字段值
<values>
<row table="categories" id="1">
<field name="name" value="Sin categoria" />
</row>
<row table="categories" id="2">
<field name="name" value="Familia" />
</row>
<row table="categories" id="3">
<field name="name" value="Amigos" />
</row>
</values>
数据库语言xml规范以及操作如下:
<database name="nombre_db" version="1" languages="es|en|de">
<field name="titulo" obligatory="true" type="multilanguage" /> //多种语言操作
DataFramework.getInstance().setForceLanguage("en"); //实例
如何它们使用?
//初始化
try {
DataFramework.getInstance().open(this, "com.tu.paquete");
} catch (Exception e) {
e.printStackTrace();
}
//不使用了就关闭它
DataFramework.getInstance().close();
Entity 的使用如下:
创建一个新的记录
Entity ent = new Entity("categoria");
ent.setValue("nombre", "Coche");
ent.save();
修改记录
Entity ent = new Entity("categoria", 3);
ent.setValue("nombre", "Motocicleta");
ent.save();
删除一条记录
Entity ent = new Entity("categoria", 3);
ent.delete();
浏览表
List<Entity> categories = DataFramework.getInstance().getEntityList("personal",
"categoria_id = 3", "fecha asc");
Iterator iter = categories.iterator();
while (iter.hasNext()) {
Entity ent = (Entity)iter.next();
System.out.println(ent.getString("nombre"));
}
从数据库中的数据装入一个微调
private Spinner mCategory;
private List<Entity> categories;
...
categories = DataFramework.getInstance().getEntityList("categories", "", "position asc");
ArrayAdapter<Entity> adapter = new ArrayAdapter<Entity>(this,
android.R.layout.simple_spinner_item, categories);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mCategory.setAdapter(adapter);
好了,来看一个实例:
public class Ejemplo extends ListActivity { //主界面
private RowEjemploAdapter adapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
DataFramework.getInstance().open(this, "com.tu.paquete");
} catch (Exception e) {
e.printStackTrace();
}
setContentView(R.layout.main);
adapter = new RowEjemploAdapter(this, DataFramework.getInstance().getEntityList("categories"));
setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(this, "Id: " + adapter.getItem(position).getId(), Toast.LENGTH_LONG).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
DataFramework.getInstance().close();
}
}
public class RowEjemploAdapter extends BaseAdapter { //适配器
private Context mContext;
private List<Entity> elements;
public RowEjemploAdapter (Context mContext, List<Entity> elements)
{
this.mContext = mContext;
this.elements = elements;
}
public int getCount() {
return elements.size();
}
public Entity getItem(int position) {
return (Entity)elements.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Entity item = elements.get(position);
View v = View.inflate(mContext, R.layout.row, null);
TextView lTitle = (TextView)v.findViewById(R.id.name);
lTitle.setText(item.getString("name"));
return v;
}
}
Main.xml 布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@id/android:list"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@id/android:empty"
android:text="@string/no_items"
android:gravity="center_vertical|center_horizontal" />
</RelativeLayout>
row.xml xml赋值
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="nombre" android:id="@+id/name"/></LinearLayout>
既然是数据库操作,当然也支持sql语句,如下规范经测试也行。
db.execSQL("CREATE TEMPORARY TABLE __"
+ DB_TABLE
+ " (_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR UNIQUE, times_used int(3) DEFAULT(0),"
+ " selected BOOLEAN DEFAULT(0), updated_at LONG DEFAULT(0), color INTEGER DEFAULT(0)); "
+ "INSERT INTO __" + DB_TABLE + " SELECT _id, name, times_used, selected, updated_at, color FROM " + DB_TABLE + ";"
+ "DROP TABLE " + DB_TABLE + ";"
+ "CREATE TABLE "
+ DB_TABLE
+ " (_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR UNIQUE, times_used int(3) DEFAULT(0),"
+ " selected BOOLEAN DEFAULT(0), updated_at LONG DEFAULT(0), color INTEGER DEFAULT(0));"
+ "INSERT INTO " + DB_TABLE + " SELECT _id, name, times_used, selected, updated_at, color FROM __" + DB_TABLE + ";"
+ "DROP TABLE __" + DB_TABLE + ";");