SQLite 是一款非常流行的嵌入式数据库,它支持 SQL 查询,并且只用很少的内存。Android 在运行时集成了 SQLite,所以每个 Android 应用程序都可以使用 SQLite 数据库。对数熟悉 SQL 的开发人员来时,使用 SQLite 相当简单。SQLite 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 CREATE TABLE 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,SQLite 将检查它的类型。如果该类型与关联的列不匹配,则 SQLite 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(String)放入 INTEGER 列。但是当一个列声明为INTEGER PRIMARY KEY时,只能存储64位整数,否则会发生异常。SQLite 称这为“弱类型”(manifest typing.)。此外,SQLite 不支持一些标准的 SQL 功能,特别是外键约束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN, 还有一些 ALTER TABLE 功能。除了上述功能外,SQLite 是一个完整的 SQL 系统。

Android中,数据库存储在 data/< 项目文件夹 >/databases/ 下。

Activites 可以通过 Content Provider 或者 Service 访问一个数据库。下面会详细讲解如果创建数据库,添加数据和查询数据库。

Android 不自动提供数据库。在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。Android 提供了 SQLiteOpenHelper 帮助你创建一个数据库,你只要继承 SQLiteOpenHelper 类,就可以轻松的创建数据库。SQLiteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。SQLiteOpenHelper 的子类,至少需要实现三个方法:

  • 构造函数,调用父类 SQLiteOpenHelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 Activity),数据库名字,一个可选的游标工厂(通常是 Null),一个代表你正在使用的数据库模型版本的整数。
  • onCreate()方法,它需要一个 SQLiteDatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。
  • onUpgrage() 方法,它需要三个参数,一个 SQLiteDatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。 下面示例代码展示了如何继承 SQLiteOpenHelper 创建数据库:
package com.liuzhichao.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBHelper extends SQLiteOpenHelper {

	private final static String TAG = "DBHelper";
	private final static String DBNAME = "books.db"; // 数据库名
	private final static String TABLENAME = "book"; // 表名
	private final static int DBVERSION = 1; // 数据库版本
	private final static String KEY_ID = "_id";
	private final static String KEY_NAME = "name";
	private final static String KEY_PUBLISHER = "publisher";
	private final static String TABLESQL = "create table if not exists "
			+ TABLENAME + " (" + KEY_ID + " integer primary key," + KEY_NAME
			+ " varchar," + KEY_PUBLISHER + " varchar)";

	public DBHelper(Context context) {
		super(context, DBNAME, null, DBVERSION);
	}
	/**
	 * 数据库被创建后执行的方法, 该方法执行一次,通常用来创建表
	 * @param db
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(TABLESQL);
		Log.i(TAG, "Create Table:"+TABLESQL);
	}

	/**
	 * 当打开数据库时传入的版本号与当前的版本号不同时会调用该方法
	 *
	 * @param db
	 * @param oldVersion
	 * @param newVersion
	 */
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO 更改数据库版本的操作
		Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
				+ newVersion + ", which will destroy all old data");
		db.execSQL("DROP TABLE IF EXISTS titles");
		onCreate(db);
	}
}

我们新建一个数据库books.db,创建了一张表book,有三个字段:_id,name,publisher,然后我们新建一个实体类BookModel:

接下来是对BookModel的CRUD操作的业务代码:

package com.liuzhichao.sqlite;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class BookService {
	private DBHelper dbHelper;

	public BookService(Context context) {
		dbHelper = new DBHelper(context);
	}


	// 添加
	public void addBook(BookModel book) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		db.execSQL("insert into book(name,publisher) values(?,?)",
				new Object[] { book.getName(), book.getPublisher() });
		db.close();
	}

	// 删除
	public void delteBook(Integer id) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		db.execSQL("delete from book where _id = ?", new Object[] { id });
		db.close();
	}

	// 修改
	public void updateBook(BookModel book) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		db.execSQL(
				"update book set name = ? , publisher = ? where _id=?",
				new Object[] { book.getName(), book.getPublisher(),
						book.get_id() });
		db.close();
	}

	// 根据ID查询
	public Cursor getBookById(Integer id) {
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery(
				"select _id,name,publisher from book where _id=?",
				new String[] { id.toString() });
		return cursor;
	}

	// 分页查询
	public Cursor getScroolBook(Integer offset, Integer maxResult) {
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor cursor= db
				.rawQuery(
						"select _id,name,publisher from book order by _id ASC limit ?,?",
						new String[] { offset.toString(), maxResult.toString() });
		return cursor;
	}

	// 查询记录总数
	public long getCount() {
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select count(*) from book", null);
		cursor.moveToFirst();
		return cursor.getLong(0);

	}
}

最后是操作界面,我们首先通过ListView显示前30条数据

当我们点击菜单的时候可以添加和查询数据,

当我们在ListView的某一个Item上长按的时候,可以对选择的项进行修改或是删除

代码如下:

package com.liuzhichao.sqlite;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class SQLiteDemoActivity extends Activity {

	private ListView mListView;
	private Context context;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		context = this;
		mListView = (ListView) findViewById(R.id.mListView);

		BookService service = new BookService(context);
		Cursor c = service.getScroolBook(0, 30);
		showList(c);

		//ListView长按事件处理
		mListView.setOnItemLongClickListener(new OnItemLongClickListener() {
			public boolean onItemLongClick(AdapterView<?> parent, View view,
					int position, final long id) {

				final BookService service = new BookService(context);
				//根据id查询Book信息
				Cursor cursor = service.getBookById((int) id);
				String bookName = "";
				String bookPublisher = "";
				if (cursor.moveToFirst()) {
					bookName = cursor.getString(cursor.getColumnIndex("name"));
					bookPublisher = cursor.getString(cursor
							.getColumnIndex("publisher"));
				}

				//对话框弹出的修改和删除界面
				LayoutInflater updateInflater = LayoutInflater.from(context);
				View updateView = updateInflater.inflate(R.layout.updatebook,
						null);

				final EditText et_updateid = (EditText) updateView
						.findViewById(R.id.update_id);
				final EditText et_updatename = (EditText) updateView
						.findViewById(R.id.update_name);
				final EditText et_updatepublisher = (EditText) updateView
						.findViewById(R.id.update_publisher);

				et_updateid.setText(id + "");
				et_updatename.setText(bookName);
				et_updatepublisher.setText(bookPublisher);

				//弹出对话框
				new AlertDialog.Builder(context).setTitle("修改")
						.setView(updateView)
						.setPositiveButton("修改", new OnClickListener() {
							//修改按钮事件处理
							public void onClick(DialogInterface dialog,
									int which) {
								BookService service = new BookService(context);
								BookModel book = new BookModel();
								book.set_id((int) id);
								book.setName(et_updatename.getText().toString());
								book.setPublisher(et_updatepublisher.getText()
										.toString());
								service.updateBook(book);
								//修改后"刷新"界面
								Cursor c = service.getScroolBook(0, 30);
								showList(c);
							}
						}).setNeutralButton("删除", new OnClickListener() {
							//删除按钮事件处理
							public void onClick(DialogInterface dialog,
									int which) {
								service.delteBook((int) id);
								//删除后"刷新"界面
								Cursor c = service.getScroolBook(0, 30);
								showList(c);
							}
						}).setNegativeButton("取消", new OnClickListener() {
							//取消按钮事件处理
							public void onClick(DialogInterface dialog,
									int which) {
								dialog.dismiss();
							}
						})
						.create().show();
				return false;
			}

		});
	}

	//显示ListView
	void showList(Cursor c) {
		mListView.setAdapter(new SimpleCursorAdapter(this, R.layout.list, c,
				new String[] { "_id", "name", "publisher" }, new int[] {
						R.id.book_id, R.id.book_name, R.id.book_publisher }));
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		super.onCreateOptionsMenu(menu);
		menu.add(1, 1, 1, "添加");
		menu.add(1, 2, 2, "查询");
		return true;
	}

	/**
	 * 菜单事件处理
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case 1:
			LayoutInflater factory = LayoutInflater.from(context);
			final View addbookDialogView = factory.inflate(R.layout.addbook,
					null);
			final Builder builder = new AlertDialog.Builder(context);
			builder.setTitle("添加");
			builder.setView(addbookDialogView);
			builder.setPositiveButton("添加",
					new DialogInterface.OnClickListener() {
				        //添加按钮事件处理
						public void onClick(DialogInterface dialog, int which) {
							BookService bookService = new BookService(context);
							BookModel book = new BookModel();
							EditText et_addName = (EditText) addbookDialogView
									.findViewById(R.id.add_name);
							EditText et_addPublisher = (EditText) addbookDialogView
									.findViewById(R.id.add_publisher);
							book.setName(et_addName.getText().toString());
							book.setPublisher(et_addPublisher.getText()
									.toString());
							bookService.addBook(book);
							Cursor c = bookService.getScroolBook(30, 30);
							showList(c);
						}
					});
			builder.setNegativeButton("取消",
					new DialogInterface.OnClickListener() {

						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					});
			builder.create().show();
			break;
		case 2:
			LinearLayout layout = new LinearLayout(context);
			layout.setOrientation(LinearLayout.VERTICAL);
			final EditText editText = new EditText(context);
			LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.FILL_PARENT);
			layout.addView(editText, params);
			new AlertDialog.Builder(context)
					.setView(layout)
					.setTitle("请输入图书编号")
					.setNegativeButton("取消",
							new DialogInterface.OnClickListener() {

								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							})
					.setPositiveButton("查询",
							new DialogInterface.OnClickListener() {
								//查询按钮事件处理
								public void onClick(DialogInterface dialog,
										int which) {
									Integer id = Integer.parseInt(editText
											.getText().toString());
									BookService bookService = new BookService(
											context);
									Cursor c = bookService.getBookById(id);
									showList(c);
								}
							}).create().show();
			break;
		default:
			return super.onOptionsItemSelected(item);
		}
		return true;
	}

}

其中用到的布局文件如下

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center" >
    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView
        android:text="编号"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        />
	 <TextView
        android:text="名称"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        />
	  <TextView
        android:text="出版社"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        />
</LinearLayout>
    <ListView
        android:id="@+id/mListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView
        android:id="@+id/book_id"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        />
	 <TextView
        android:id="@+id/book_name"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content"
        />
	  <TextView
        android:id="@+id/book_publisher"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="wrap_content"
        />
</LinearLayout>

addbook.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <TextView
        android:text="名称"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/add_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
     <TextView
        android:text="出版社"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
      <EditText
        android:id="@+id/add_publisher"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>