在 Android与SQLite数据库 这个专题里我们谈到了 SQLite 的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自 SQLiteOpenHelper 类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。下面,我们就以一个实例来讲解具体的用法。
程序比较简单,由以下五个文件组成:
TestDBActivity.java
listView_db.xml
User.java
DBHelper.java
DBManager.java
1. 首先编写 DBHelper,它继承了 SQLiteOpenHelper,作为维护和管理数据库的基类。
数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。
package net.nowamagic.test;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "nowamagic.db";
private static final int DATABASE_VERSION = 1;
public DBHelper(Context context) {
//CursorFactory设置为null,使用默认值
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//数据库第一次被创建时onCreate会被调用
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS user" +
"(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, info TEXT)");
}
//如果DATABASE_VERSION值被改为2,系统发现现有数据库版本不同,即会调用onUpgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTER TABLE user ADD COLUMN other STRING");
}
}
2. 为了方便我们面向对象的使用数据,我们建一个 User 类,对应 user 表中的字段,如下:
package net.nowamagic.test;
public class User {
public int _id;
public String name;
public int age;
public String info;
public User() {
}
public User(String name, int age, String info) {
this.name = name;
this.age = age;
this.info = info;
}
}
3. 然后,我们需要一个DBManager,来封装我们所有的业务方法,代码如下:
我们在DBManager构造方法中实例化DBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在添加多个Person信息时,我们采用了事务处理,确保数据完整性;最后我们提供了一个closeDB方法,释放数据库资源,这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。
package net.nowamagic.test;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.widget.Toast;
public class DBManager {
private DBHelper helper;
private SQLiteDatabase db;
Context c;
public DBManager(Context context) {
helper = new DBHelper(context);
//因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName, 0, mFactory);
//所以要确保context已初始化,我们可以把实例化DBManager的步骤放在Activity的onCreate里
db = helper.getWritableDatabase();
c = context;
}
/**
* add users
* @param users
*/
public void add(List users) {
db.beginTransaction(); //开始事务
try {
for (User user : users) {
db.execSQL("INSERT INTO user VALUES(null, ?, ?, ?)", new Object[]{user.name, user.age, user.info});
}
db.setTransactionSuccessful(); //设置事务成功完成
} finally {
db.endTransaction(); //结束事务
}
}
/**
* update user's age
* @param user
*/
public void insertUser(User user) {
ContentValues cv = new ContentValues();
cv.put("age", user.age);
cv.put("name", user.name);
cv.put("info", user.info);
long rowid = db.insert("user", null, cv);
Toast.makeText(c, "已插入一条测试数据,id =" + rowid, Toast.LENGTH_SHORT).show();
}
/**
* update user's age
* @param user
*/
public void updateAge(User user) {
ContentValues cv = new ContentValues();
cv.put("age", user.age);
db.update("user", cv, "name = ?", new String[]{user.name});
}
/**
* delete old user
* @param user
*/
public void deleteOldUser(User user) {
//db.delete("user", "age >= ?", new String[]{String.valueOf(user.age)});
int lastid = getTableRow();
user._id = lastid;
//String s = lastid;
//return lastid;
if(user._id > 0)
Toast.makeText(c, "已删除第 "+ lastid +" 行(最末行)数据", Toast.LENGTH_SHORT).show();
db.delete("user", "_id = ?", new String[]{String.valueOf(user._id)});
Log.i("nowamagicdb", "last_id=>" + lastid);
if(user._id == 0)
Toast.makeText(c, "数据库已清空", Toast.LENGTH_SHORT).show();
//db.delete("user", "_id = ?", new String[]{String.valueOf(user._id)});
}
/**
* query all users, return list
* @return List
*/
public List query() {
ArrayList users = new ArrayList();
Cursor c = queryTheCursor();
while (c.moveToNext()) {
User user = new User();
user._id = c.getInt(c.getColumnIndex("_id"));
user.name = c.getString(c.getColumnIndex("name"));
user.age = c.getInt(c.getColumnIndex("age"));
user.info = c.getString(c.getColumnIndex("info"));
users.add(user);
}
c.close();
return users;
}
/**
* query all users, return cursor
* @return Cursor
*/
public Cursor queryTheCursor() {
Cursor c = db.rawQuery("SELECT * FROM user", null);
return c;
}
/**
* close database
*/
public void closeDB() {
db.close();
}
public int getTableRow(){
Cursor c = queryTheCursor();
if (c.moveToLast() == false)
{
//为空的Cursor
return 0;
}
else
{
int user_id = c.getInt(c.getColumnIndex("_id"));
return user_id;
}
//c.moveToLast();
}
}
4. 最后就是 TestDBActivity 了:
package net.nowamagic.magicapp_v17;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import net.nowamagic.test.DBManager;
import net.nowamagic.test.User;
public class TestDBActivity extends Activity {
private DBManager mgr;
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.testdb2);
listView = (ListView) findViewById(R.id.listView_db);
//初始化DBManager
mgr = new DBManager(this);
//Toast.makeText(getApplicationContext(), "欢迎来到简明现代魔法~", Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
//应用的最后一个Activity关闭时应释放DB
mgr.closeDB();
}
public void add(View view) {
ArrayList users = new ArrayList();
User user1 = new User("Vorn", 17, "堤格尔维尔穆德·冯伦");
User user2 = new User("Eleonora Viltaria", 17, "艾蕾欧诺拉·维尔塔利亚");
User user3 = new User("Ludmilla Lurie", 16, "琉德米拉·露利叶");
User user4 = new User("Sophia Obertas", 20, "苏菲亚·欧贝达斯");
User user5 = new User("Alexandra Alshavin", 22, "亚莉莎德拉·阿尔夏芬");
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
mgr.add(users);
Toast.makeText(this, "已添加测试数据", Toast.LENGTH_SHORT).show();
query(view);
}
public void insert(View view) {
User user = new User();
user.name = "Gonn";
user.age = 99;
user.info = "简明现代魔法";
mgr.insertUser(user);
query(view);
}
public void update(View view) {
User user = new User();
user.name = "Vorn";
user.age = 20;
mgr.updateAge(user);
}
public void delete(View view) {
User user = new User();
user.age = 30;
mgr.deleteOldUser(user);
query(view);
//Toast.makeText(this, "", Toast.LENGTH_SHORT).show();
}
public void query(View view) {
List users = mgr.query();
ArrayList> list = new ArrayList>();
for (User user : users) {
HashMap map = new HashMap();
map.put("name", user.name);
map.put("info", user.age + " years old, " + user.info);
list.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2,
new String[]{"name", "info"}, new int[]{android.R.id.text1, android.R.id.text2});
listView.setAdapter(adapter);
}
public void queryTheCursor(View view) {
Cursor c = mgr.queryTheCursor();
startManagingCursor(c); //托付给activity根据自己的生命周期去管理Cursor的生命周期
CursorWrapper cursorWrapper = new CursorWrapper(c) {
@Override
public String getString(int columnIndex) {
//将简介前加上年龄
if (getColumnName(columnIndex).equals("info")) {
int age = getInt(getColumnIndex("age"));
return age + " years old, " + super.getString(columnIndex);
}
return super.getString(columnIndex);
}
};
//确保查询结果中有"_id"列
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2,
cursorWrapper, new String[]{"name", "info"}, new int[]{android.R.id.text1, android.R.id.text2});
ListView listView = (ListView) findViewById(R.id.listView_db);
listView.setAdapter(adapter);
}
}
其XML如下:
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="2">
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="add"
android:onClick="add"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="insert"
android:onClick="insert"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="update"
android:onClick="update"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="delete"
android:onClick="delete"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="query"
android:onClick="query"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="queryCursor"
android:onClick="queryTheCursor"/>
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
android:id="@+id/listView_db"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
演示效果如下:
后面分小节去慢慢解析这个简单的程序。