經驗: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);