day03數據庫及listview

經驗:1.sqlite表中的類型限定并不起作用,底層所有的數據都是String,為了節約手機內存

2.4.0版本以后數據庫在創建時會產生一個臨時文件

3.4.4版本以后虛擬機引用了ART模式,使速度更快

4.開發分包示例

1.android下數據庫的創建

什么時候使用數據庫做數據存儲? 有大量具有相同結構的數據需要存儲時。

mysql sql2008 sqlite 內置的 輕量級

SqliteOpenHelper:

1.創建一個類繼承SqliteOpenHelper,寫一個構造方法用來指定數據庫的名稱版本

2.實現兩個方法:

//構造方法 ,用來指定數據庫的名稱和版本號

public MySqliteOpenHelper(Context context) {

//context :上下文?? name: 數據庫文件的名稱? factory:用來創建cursor對象,默認傳null?? version:數據庫的版本,從android4.0之后只能升不能降。

super(context, "info.db", null, 2);

}

onCreate:數據庫第一次創建的時候調用onCreate方法, 特別適合做表結構的初始化

//數據庫第一次創建的時候調用onCreate方法, 特別適合做表結構的初始化

@Override

public void onCreate(SQLiteDatabase db) {

//做表結構的初始化就需要執行create table這樣的sql語句

//使用db執行sql語句

db.execSQL("create table info (_id integer primary key autoincrement ,name varchar(20) )");

}

//當數據庫的版本發生改變的時候會調用onUpgrade方法;特別適合做表結構的修改

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//做表結構的修改需要執行sql語句

//????????? db.execSQL("alter table info add? phone varchar(20)");

System.out.println("oldVersion:"+oldVersion +"? newVersion: "+newVersion);

}

onUpgrade:當數據庫的版本發生改變的時候會調用onUpgrade方法;特別適合做表結構的修改

3.創建一個幫助類的實例化對象,并調用getReadableDatabase或getWritableDatabase方法,可以幫助我們創建或打開一個數據庫。

*******getReadableDatabase和getWritableDatabase區別:

getReadableDatabase:首先嘗試以讀寫的方式打開數據庫,如果磁盤空間滿了,會再次嘗試以只讀方式打開數據庫。

getWritableDatabase: 直接以讀寫方式打開數據庫,如果磁盤空間滿了,直接報錯。

2.Android下數據庫的第一種增刪改查方法(沒有返回值,適合查詢使用)

public class InfoDaoUtils {

private MySqliteOpenHelper mySqliteOpenHelper;

public InfoDaoUtils (Context context){

//1.創建幫助類對象

mySqliteOpenHelper = new MySqliteOpenHelper(context);

}

//增加方法

public void insert(UserBean bean){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();//這個方法不要再構造函數中初始化,不方便數據庫操作

//3.執行sql語句? sql:sql語句?? bindArgs:?sql語句中占位符的值。

db.execSQL("insert into info(name,phone) values(?,?);", new Object[]{bean.name,bean.phone});

//4.關閉數據庫對象

db.close();

}

//刪除方法

public void delete(String name){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句? sql:sql語句?? bindArgs:?sql語句中占位符的值。

db.execSQL("delete from info where name=?;", new Object[]{name});

//4.關閉數據庫對象

db.close();

}

//更新方法

public void update(UserBean newuserBean){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句? sql:sql語句?? bindArgs:?sql語句中占位符的值。

db.execSQL("update info set phone=? where name=?;", new Object[]{newuserBean.phone,newuserBean.name});

//4.關閉數據庫對象

db.close();

}

//查詢方法

public void query(String name){

//執行sql語句需要SqliteDatabase對象

ArrayList list = new ArrayList();

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句? sql:sql語句?? selectionArgs:?sql語句中查詢條件的占位符的值。? 返回一個cursor游標結果集對象

Cursor cursor = db.rawQuery("select name,phone from info where name = ? ", new String[]{name});

//4.獲取結果集中的數據封裝到list中

if(cursor != null && cursor.getCount() > 0){//說明結果集中有數據

while(cursor.moveToNext()){//游標可以指向下一行

//解析一行數據

String name_str = cursor.getString(cursor.getColumnIndex("name"));//通過獲取字段編號再獲得字段值,不會弄錯編號

String phone_str = cursor.getString(cursor.getColumnIndex("phone"));

System.out.println("name : "+name_str + "? phone:"+phone_str);

UserBean userBean = new UserBean();

userBean.name = name_str;

userBean.phone = phone_str;

list.add(userBean);

}

//關閉游標對象

cursor.close();

}

//5.關閉數據庫對象

db.close();

}

3.Android下另一種增刪改查(谷歌封裝的API,有返回值,適合增刪改)

public class InfoDaoUtils2 {

private MySqliteOpenHelper mySqliteOpenHelper;

public InfoDaoUtils2 (Context context){

//1.創建幫助類對象

mySqliteOpenHelper = new MySqliteOpenHelper(context);

}

//增加方法

public boolean insert(UserBean bean){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

// db.execSQL("insert into info(name,phone) values(?,?);", new Object[]{bean.name,bean.phone});

ContentValues values = new ContentValues();//底層封裝的是一個map

values.put("name", bean.name);

values.put("phone", bean.phone);

//3.執行sql語句

//table: 表名 nullColumnHack:可以為null values:封裝要添加的列的值 返回值:新添加這一行的行的id,如果是-1標示添加失敗

long result = db.insert("info", null, values);

//4.關閉數據庫對象

db.close();

if(result == -1){

return false;

}else{

return true;

}

}

//刪除方法

public int delete(String name){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句

//table:表名 whereClause:刪除的條件 whereArgs:刪除條件占位符的值 返回值:成功刪除了多少行

int result = db.delete("info", "name=?", new String []{name});

//4.關閉數據庫對象

db.close();

return result;

}

//更新方法

public int update(UserBean newuserBean){

//執行sql語句需要SqliteDatabase對象

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句

ContentValues values = new ContentValues();

values.put("phone", newuserBean.phone);

//table: values:要更新的列 whereClause:更新條件 whereArgs:更新條件占位符的值 返回值:成功修改了多少行

int result = db.update("info", values, "name=?", new String[]{newuserBean.name});

//4.關閉數據庫對象

db.close();

return result;

}

//查詢方法

public void query(String name){

//執行sql語句需要SqliteDatabase對象

ArrayList list = new ArrayList();

//2.調用getReadableDatabase獲取一個SqliteDatabase對象

SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();

//3.執行sql語句

//table :表名 columns:查詢哪些列 ,如果傳null代表查詢所有列 selection:查詢的條件 selectionArgs:條件占位符的值 groupBy:按什么分組 having:分組的條件 orderBy :按什么排序

Cursor cursor = db.query("info", new String[]{"name","phone"}, "name = ?", new String[]{name}, null, null, "_id desc");

//4.獲取結果集中的數據封裝到list中

if(cursor != null && cursor.getCount() > 0){//說明結果集中有數據

while(cursor.moveToNext()){//游標可以指向下一行

//解析一行數據

String name_str = cursor.getString(cursor.getColumnIndex("name"));

String phone_str = cursor.getString(cursor.getColumnIndex("phone"));

System.out.println("name : "+name_str + " phone:"+phone_str);

UserBean userBean = new UserBean();

userBean.name = name_str;

userBean.phone = phone_str;

list.add(userBean);

}

//關閉游標對象

cursor.close();

}

//5.關閉數據庫對象

db.close();

}

}

4.數據庫事務(適合銀行操作,代碼塊中同時成功或者同時失敗)

1.事務對于查詢安全性的作用

//做轉賬業務,執行sql語句

public void transtationAccount(View v){

AccountSqliteOpenHelper accountSqliteOpenHelper = new AccountSqliteOpenHelper(this);

SQLiteDatabase db = accountSqliteOpenHelper.getReadableDatabase();

//開啟事務

db.beginTransaction();

try {

db.execSQL("update account set money= money-200 where name=?",new String[]{"李四"});

//模擬一個異常

int i = 100/0;

db.execSQL("update account set money= money+200 where name=?",new String[]{"張三"});

db.setTransactionSuccessful();//設置一個成功的標記

} finally {

db.endTransaction();//結束事務,要判斷事務是否成功,如果成功提交所有sql語句,如果失敗,回滾所有的sql語句

}

db.close();

}

2.事務對于提高數據庫批量操作效率的作用

在批量修改數據的時候,由于事務是在進行事務提交時將要執行的SQL操作一次性打開數據庫連接執行,其執行速度比逐條執行SQL語句的速度快了很多倍。因此當我們開發中遇到對數據庫的批量操作那么,使用事務是提高效率的重要原則。

publicvoidtestTransactionEfficient(){

PersonOpenHelper helper =newPersonOpenHelper(getContext(),"person",null, 2);

SQLiteDatabase database = helper.getWritableDatabase();

//?????------測試不使用事務時插入1w條數據耗時--------------------

longbeginTime = System.currentTimeMillis();

for(inti=0;i<10000;i++){

database.execSQL("insert into person(name,age,phone) values('text'+"+i+","+i+",'"+(1320000+i)+""+"')");

}

longendTime = System.currentTimeMillis();

System.out.println("不使用事務插入1w條數據耗時:"+(endTime-beginTime)+"毫秒");

//?????---------測試使用事務時耗時-----------------------

beginTime = System.currentTimeMillis();

database.beginTransaction();

for(inti=0;i<10000;i++){

database.execSQL("insert into person(name,age,phone) values('text'+"+i+","+i+",'"+(1320000+i)+""+"')");

}

database.setTransactionSuccessful();

database.endTransaction();

endTime = System.currentTimeMillis();

System.out.println("使用事務插入1w條數據耗時:"+(endTime-beginTime)+"毫秒");

5.獲取listview顯示的步驟

ListView 是一個在垂直滾動的列表中展示條目的控件。ListView上的條目內容來自于ListAdapter.

1.寫布局

2.activity中找到listview

3.寫一個類繼承BaseAdapter,實現4個方法。

getcount:告訴listview要顯示多少個條目

getItem:獲取listview指定position條目上的數據對象。 該方法不影響listview的展示,可以先不實現。

getItemId:獲取listview指定條目的id. 該方法不影響listview的展示,可以先不實現。

getView:告訴listview每個條目上顯示的內容。 listview每顯示一個條目getView方法就會被調用一次。 convertView:之前消失的那個item上的view對象

4.創建一個Adapter對象,設置給listview做條目的適配

listview.setAdapter(ListAdapter adapter)

6 常用獲取inflate的寫法

a.使用View.inflate

//需要創建一個復雜的布局轉換成一個view對象。 context :上下文 ,resource :要填充的布局資源的id root:將要填充的布局用root包裹起來返回,一般傳null

view = View.inflate(context, R.layout.item_news, null);//將一個布局文件填充成一個view對象

b.使用context.getSystemService

LayoutInflater layoutInfalter = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

view = layoutInfalter.inflate(R.layout.item_news, null);

c.使用LayoutInflate.from

LayoutInflater layoutInfalter = LayoutInflater.from(context);

view = layoutInfalter.inflate(R.layout.item_news, null);

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。