---------------------- android培訓、java培訓、期待與您交流! ----------------------
第三天
1、爲了實現對數據庫版本進行管理,SQLiteOpenHelper類提供了兩個重要的方法,分別是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用於初次使用軟件時生成數據庫表,後者用於升級軟件時更新數據庫表結構。當調用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用於操作數據庫的SQLiteDatabase實例的時候,如果數據庫不存在,Android系統會自動生成一個數據庫,接着調用onCreate()方法,onCreate()方法在初次生成數據庫時纔會被調用,在onCreate()方法裏可以生成數據庫表結構及添加一些應用使用到的初始化數據。onUpgrade()方法在數據庫的版本發生變化時會被調用,一般在軟件升級時才需改變版本號,而數據庫的版本是由程序員控制的,假設數據庫現在的版本是1,由於業務的變更,修改了數據庫表結構,這時候就需要升級軟件,升級軟件時希望更新用戶手機裏的數據庫表結構,爲了實現這一目的,可以把原來的數據庫版本設置爲2(有同學問設置爲3行不行?當然可以,如果你願意,設置爲100也行),並且在onUpgrade()方法裏面實現表結構的更新。當軟件的版本升級次數比較多,這時在onUpgrade()方法裏面可以根據原版號和目標版本號進行判斷,然後作出相應的表結構及數據更新。
getWritableDatabase()和getReadableDatabase()方法都可以獲取一個用於操作數據庫的SQLiteDatabase實例。但getWritableDatabase() 方法以讀寫方式打開數據庫,一旦數據庫的磁盤空間滿了,數據庫就只能讀而不能寫,倘若使用的是getWritableDatabase() 方法就會出錯。getReadableDatabase()方法先以讀寫方式打開數據庫,如果數據庫的磁盤空間滿了,就會打開失敗,當打開失敗後會繼續嘗試以只讀方式打開數據庫。
數據庫創建:
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
…………
public class PersonDBCreate extends SQLiteOpenHelper {
public PersonDBCreate(Context context) {
super(context, "personDB.db", null, 1); }
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table if not exists person_table ("
+ "id integer primary key autoincrement,name varchar(10),age int)"); }
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }}
數據庫操作:
import java.util.ArrayList;
import java.util.List;
import cn.lx.bean.Person;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class PersonDBOperate {
private SQLiteDatabase db;
public PersonDBOperate(SQLiteDatabase db) {
this.db = db; }
public void insert(List<Person> persons) {
for (Person p : persons) {
db.execSQL("insert into person_table(name,age) values (?,?)",
new Object[] { p.getName(), p.getAge() }); } }
public void delete(int id) {
db.execSQL("delete from person_table where id=?", new Integer[] { id }); }
public void update(Person person) {
db.execSQL(
"update person_table set name=?,age=? where id=?",
new Object[] { person.getName(), person.getAge(),
person.getId() }); }
public Person find(int id) {
Person p = new Person();
Cursor c = db.rawQuery("select * from person_table where id=?",
new String[] { id + "" });
if (c.moveToFirst()) {
p.setId(id);
p.setName(c.getString(c.getColumnIndex("name")));
p.setAge(c.getInt(c.getColumnIndex("age"))); }
return p; }
public int getCount() {
Cursor c = db.rawQuery("select count(*) from person_table", null);
c.moveToFirst();
return c.getInt(0); }
public List<Person> getPersons() {
List<Person> persons = new ArrayList<Person>();
Person p = null;
Cursor c = db.rawQuery("select * from person_table", null);
c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
p = new Person();
p.setId(c.getInt(c.getColumnIndex("id")));
p.setAge(c.getInt(c.getColumnIndex("age")));
p.setName(c.getString(c.getColumnIndex("name")));
persons.add(p);
p = null;
c.moveToNext(); }
return persons; }}
數據庫操作方法測試:
import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;
import android.util.Log;
…………
public class TestPersonDBOperate extends AndroidTestCase {
PersonDBCreate pC = null;
SQLiteDatabase db = null;
PersonDBOperate po = null;
public void insertTest() {
pC = new PersonDBCreate(getContext());
db = pC.getWritableDatabase();
po = new PersonDBOperate(db);
List<Person> persons = null;
Person p = null;
persons = new ArrayList<Person>();
for (int i = 0; i < 10; i++) {
p = new Person();
p.setAge(20+i);
p.setName("name" + i);
p.setId(i);
persons.add(p);
p = null; }
po.insert(persons); }
………………
}
使用SQLiteDatabase自帶方法操作數據庫:
delete(String table, String whereClause, String[] whereArgs)
insert(String table, String nullColumnHack, ContentValues values)
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
update(String table,ContentValues values,String whereClause, String[] whereArgs)
2.事務操作:
使用SQLiteDatabase的beginTransaction()方法可以開啓一個事務,程序執行到endTransaction() 方法時會檢查事務的標誌是否爲成功,如果程序執行到endTransaction()之前調用了setTransactionSuccessful() 方法設置事務的標誌爲成功則提交事務,如果沒有調用setTransactionSuccessful() 方法則回滾事務。使用例子如下:
SQLiteDatabase db = ....;
db.beginTransaction();//開始事務
try {
db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"傳智播客", 4});
db.execSQL("update person set name=? where personid=?", new Object[]{"傳智", 1});
db.setTransactionSuccessful();//調用此方法會在執行到endTransaction() 時提交當前事務,如果不調用此方法會回滾事務
} finally {
db.endTransaction();//由事務的標誌決定是提交事務,還是回滾事務
}
db.close();
上面兩條SQL語句在同一個事務中執行。
3.ListView用法(形如android系統設置界面):
1)、先定義每一項(item)的顯示佈局,通常用TextView控件佈局。
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="80dip"
android:layout_height="wrap_content"
android:text="435"
android:id="@+id/id"
/>
<TextView
android:layout_width="100dip"
android:layout_height="wrap_content"
android:text="liming"
android:id="@+id/name"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="45"
android:id="@+id/amount"
/>
</LinearLayout>
2)、在主界面佈局文件中修改控件:main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="fill_parent"
android:id="@+id/listView"
/>
</LinearLayout>
3)、從數據源獲取數據,使用適配器把它綁定到ListView中,並且爲每項數據指定item界面。
//假設從數據庫中獲得的字段爲id、name、amount的數據
List<Person> persons = personService.getScrollData(0, 5);
List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
for(Person person : persons){
HashMap<String, Object> item = new HashMap<String, Object>();
item.put("id", person.getId());
item.put("name", person.getName());
item.put("amount", person.getAmount());
data.add(item);
}
//SimpleAdapter(Context context, List<? extends Map<String,?>> data, int resource, String[] from, int[] to)
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item,
new String[]{"id", "name", "amount"}, new int[]{R.id.id, R.id.name, R.id.amount});
listView.setAdapter(adapter);
備註:可以在ListView標籤上加item佈局以使之與每一個選項對應的字段說明。形成如下
顯示效果:
4)、爲點擊的item增加點擊事件(在以上代碼中加入下面的代碼):
//單擊時顯示數據的id
listView.setOnItemClickListener(new OnItemClickListener() {
//onItemClick(AdapterView<?> parent, View view, int position, long id) public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ListView lView = (ListView)parent;
//得到點擊選項的數據。
HashMap<String, Object> item = (HashMap<String, Object>)lView.getItemAtPosition(position);
Toast.makeText(MainActivity.this, item.get("id").toString(), 1).show();
}
});
5)、假如要綁定的數據是Cursor,也可以使用以下適配器綁定數據:
Cursor cursor = personService.getCursorScrollData(0, 5);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, new String[]{"_id", "name", "amount"},
new int[]{R.id.id, R.id.name, R.id.amount});
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //注意與前面的方法對比
ListView lView = (ListView)parent;
Cursor data = (Cursor)lView.getItemAtPosition(position);
int personid = data.getInt(data.getColumnIndex("_id"));
Toast.makeText(MainActivity.this, personid+"", 1).show();
} });
注:當使用這個適配器是,要求cursor中必須有字段__id(一般_id爲主鍵名),此時,在查詢時,可以重命名某個字段。
---------------------- android培訓、java培訓、期待與您交流! ----------------------