由于很难使用SharedPreferences和文件存储的方式来储存数据量大、结构性复杂的数据,而Android又内置了一套轻量级的SQLite关系型数据库。所以让我们一起来学习吧!
android为了让我们更方便的管理数据库,为我们提供了一个SQLiteOpenHelper帮助类。
由于它是一个抽象类,所以我们必须定义一个自己的帮助类去继承它,并且重写其中的onCreate()和onUpgrade()方法。通常我们在onCreate()中执行建表的操作,而onUpgrade()中的逻辑仅当传入较之前高的版本号才会执行。
在这个类中,我们还需要重写SQLiteOpenHelper的构造方法。构造方法有两个,我们通常使用参数较少哪一个。第一个参数:Context;第二个参数:是数据库的名称;第三个参数:允许在查询数据时返回一个自定义的Cursor,一把传入的是null;第四个参数:传入的是版本号。
除此之外你还需要知道两个重要的实例方法:getReadableDatabases()和getWritableDatabase()。这两个方法都可以创建或打开一个数据库并返回一个可以对数据库进行读写的操作对象;区别在于:当数据库不可写入时,前者会打开一个只读的数据库,后者会报错。
下面通过例子来看一下:
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book (" + "id integer primary key autoincrement, " + "author text, " + "price real, " + "pages integer, " + "name text) "; private Context mContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
public class MainActivity extends Activity implements View.OnClickListener { private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1); Button createDatabase = (Button) findViewById(R.id.create_database); createDatabase.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; default: break; } } }activity_main代码就不放上来了,后面的也是。里面仅放入按钮控件。
run之后我们点击创建按钮,就会有Toast告诉我们,创建成功啦。此时,你可以通过adb shell命令查看数据库、建表语句、表名等等。由于后面仍然需要使用到adb shell命令行,不会的话建议先查资料弄懂基本的操作。
前面讲到了,当传入更高版本号的时候,就会执行onUpgrade()方法,下面来看一下例子:
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_CATEGORY = "create table Category (" + "id integer primary key autoincrement, " + "category_name text, " + "category_code integer) "; public static final String CREATE_BOOK = "create table Book (" + "id integer primary key autoincrement, " + "author text, " + "price real, " + "pages integer, " + "name text) "; private Context mContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists Book"); db.execSQL("drop table if exists Category"); onCreate(db);
public class MainActivity extends Activity implements View.OnClickListener{ private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2); //传入较高版本号是为了执行MyDatabaseHelper的onUpgrade方法。 Button createDatabase = (Button) findViewById(R.id.create_database); createDatabase.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; default: break; } } }
然后,传入更高的版本号,让其执行onUpgrade方法(必须先drop掉之前已经创建的表,才能调用onCreate)
这时再用shell命令行就可以看到数据库中存在两张表了。
在进行数据添加之前,你必须先找到SQLiteDatabase提供的insert()方法,该方法传入三个参数。第一个参数:需要添加数据的表的表名;第二个参数:用于给某些未指定的列自动赋值为NULL,一般传入null;第三个参数:一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据。
了解完insert()方法之后,来看一下例子:
public class MainActivity extends Activity implements View.OnClickListener{ private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2); //传入较高版本号是为了执行MyDatabaseHelper的onUpgrade方法。 Button createDatabase = (Button) findViewById(R.id.create_database); Button addDatabase = (Button) findViewById(R.id.add_database); createDatabase.setOnClickListener(this); addDatabase.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; case R.id.add_database: SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("author", "Guo Lin"); values.put("price", 79.00); values.put("pages", 552); values.put("name", "The First Android Code"); db.insert("Book", null, values); values.clear(); values.put("author", "Doctor Xu"); values.put("price", 69.99); values.put("pages", 328); values.put("name", "Android Heroes"); db.insert("Book", null, values); break; default: break; } } }在shell命令栏输入SQL查询语句,select * from Book就可以看到我们创建的两本书,以及相关信息了。
与增添数据一样,在更新数据之前我们必须先了解SQLiteDatabase提供的update()方法,需要传入四个参数。第一个参数:需要更新数据的表的表名;第二个参数:ContentValues对象;第三第四个参数:用来约束需要更新的某一行或某几行,不指定的话就是默认更新所有行。下面来看一下例子。
public class MainActivity extends Activity implements View.OnClickListener{ private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2); //传入较高版本号是为了执行MyDatabaseHelper的onUpgrade方法。 Button createDatabase = (Button) findViewById(R.id.create_database); Button addDatabase = (Button) findViewById(R.id.add_database); Button updateDatabase = (Button) findViewById(R.id.update_database); createDatabase.setOnClickListener(this); addDatabase.setOnClickListener(this); updateDatabase.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; case R.id.add_database: SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("author", "Guo Lin"); values.put("price", 79.00); values.put("pages", 552); values.put("name", "The First Android Code"); db.insert("Book", null, values); values.clear(); values.put("author", "Doctor Xu"); values.put("price", 69.99); values.put("pages", 328); values.put("name", "Android Heroes"); db.insert("Book", null, values); break; case R.id.update_database: db = dbHelper.getWritableDatabase(); values = new ContentValues(); values.put("price", 109.99); db.update("Book", values, "name = ?", new String[] {"The First Android Code"}); break; default: break; } } }此时,我们通过第三个参数“name = ?” 来约束要更新价格为109.99的书的书名为?(?是一个占位符),然后通过第四个参数传入要更新书的书名就完成指定更新某个数据。这里我们通过上述代码将《第一行Android代码》的价格从79.00更新到了109.99。
同样,在删除数据之前,我们必须先了解SQLiteDatabase提供的delete()方法,需要传入三个参数。第一个:表名;第二、三个参数:约束删除某一行或某几行数据,不指定的话就默认删除所有行。例子如下:
public class MainActivity extends Activity implements View.OnClickListener{ private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2); //传入较高版本号是为了执行MyDatabaseHelper的onUpgrade方法。 Button createDatabase = (Button) findViewById(R.id.create_database); Button addDatabase = (Button) findViewById(R.id.add_database); Button updateDatabase = (Button) findViewById(R.id.update_database); Button deleteDatabse = (Button) findViewById(R.id.delete_database); createDatabase.setOnClickListener(this); addDatabase.setOnClickListener(this); updateDatabase.setOnClickListener(this); deleteDatabse.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; case R.id.add_database: SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("author", "Guo Lin"); values.put("price", 79.00); values.put("pages", 552); values.put("name", "The First Android Code"); db.insert("Book", null, values); values.clear(); values.put("author", "Doctor Xu"); values.put("price", 69.99); values.put("pages", 328); values.put("name", "Android Heroes"); db.insert("Book", null, values); break; case R.id.update_database: db = dbHelper.getWritableDatabase(); values = new ContentValues(); values.put("price", 109.99); db.update("Book", values, "name = ?", new String[] {"The First Android Code"}); break; case R.id.delete_database: db = dbHelper.getWritableDatabase(); db.delete("Book", "pages > ?", new String[] {"500"}); break; default: break; } } }这样,我们就删除了页数大于500页的Book,再次查看表中数据情况看也发现,《第一行Android代码》已经被删掉了。
下面我们就要来看,最重要、最复杂的查询数据。查询数据复杂所在正是SQLiteDatabase提供的query()方法最少的一个重载都需要传入七个参数。第一个参数:表名;第二个参数:指定去查询那几列,默认为查询所有列;第三四个参数:约束查询某一行或某几行;第五个参数:对查询结果进行group by;第六个参数:将group by 之后的数据进一步过滤;第七个参数:指定查询结果的排序方式,不指定则按默认方式排序。下面来看一个简单的例子:
public class MainActivity extends Activity implements View.OnClickListener{ private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 3); //传入较高版本号是为了执行MyDatabaseHelper的onUpgrade方法。 Button createDatabase = (Button) findViewById(R.id.create_database); Button addDatabase = (Button) findViewById(R.id.add_database); Button updateDatabase = (Button) findViewById(R.id.update_database); Button deleteDatabase = (Button) findViewById(R.id.delete_database); Button queryDatabase = (Button) findViewById(R.id.query_database); createDatabase.setOnClickListener(this); addDatabase.setOnClickListener(this); updateDatabase.setOnClickListener(this); deleteDatabase.setOnClickListener(this); queryDatabase.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.create_database: dbHelper.getWritableDatabase(); break; case R.id.add_database: SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("author", "Guo Lin"); values.put("price", 79.00); values.put("pages", 552); values.put("name", "The First Android Code"); db.insert("Book", null, values); values.clear(); values.put("author", "Doctor Xu"); values.put("price", 69.99); values.put("pages", 328); values.put("name", "Android Heroes"); db.insert("Book", null, values); break; case R.id.update_database: db = dbHelper.getWritableDatabase(); values = new ContentValues(); values.put("price", 109.99); db.update("Book", values, "name = ?", new String[] {"The First Android Code"}); break; case R.id.delete_database: db = dbHelper.getWritableDatabase(); db.delete("Book", "pages > ?", new String[] {"500"}); break; case R.id.query_database: db = dbHelper.getWritableDatabase(); Cursor cursor = db.query("Book", null, null, null, null, null, null); if (cursor.moveToFirst()) do { String name = cursor.getString(cursor.getColumnIndex("name")); String author = cursor.getString(cursor.getColumnIndex("author")); int pages = cursor.getInt(cursor.getColumnIndex("pages")); double price = cursor.getDouble(cursor.getColumnIndex("price")); Log.d("MainActivity", "Book name is " + name); Log.d("MainActivity", "Book author is " + author); Log.d("MainActivity", "Book price is " + price); Log.d("MainActivity", "Book pages is " + pages); } while (cursor.moveToNext()); cursor.close(); break; default: break; } } }这时,我们点击QUERY DATABASE按钮,在logcat中可以看见《Android群英传》这本书及相关信息。当传入版本号为3并重写运行之后,点击CREATE DATABASE 以及 ADD DATABASE按钮之后,再次点击QUERY DATABASE按钮可以在logcat中看到《第一行Android代码》和《Android群英传》两本书的信息。