开源项目之Android DataFramework(数据库框架)

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 + ";");


介绍完毕,欢迎使用,项目下载!


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值