您好,登錄后才能下訂單哦!
開源數據庫開源庫:
Ormlite
SQLite支持的字段類型及建表
http://boonya.iteye.com/blog/2118252
SQLite查詢
http://www.cnblogs.com/Excellent/archive/2011/11/19/2254888.html
一、Android中的數據庫的創建和操作
????在Android中如果進行大量的具有相同數據結構存儲時,需要用到SQLite數據庫。
? 1.SQLite的特點:
????1)它是一個輕量級的數據庫,其實就是一個文件。當然它的容量有有限的,畢竟是運行在
? ? ? ?手機Android系統中的。
????2)它雖然小,但是它功能卻十分的強大,操作起來非常簡便。
? 2.SQLite的創建
????第1步:創建一個類繼承SQLiteOpenHelper類,實現它的2個方法onCreate()和onUpgrade()。
public?class?MyOpenHelper?extends?SQLiteOpenHelper?{ //本來構造方法應該有4個參數,super調用的時候把參數寫死了,這里就只傳context參數了。 public?MyOpenHelper(Context?context)?{ /* ?*?Parameters context? 上下文 name? SQLite數據庫名稱 factory? 用于創建Cursor,一般寫null。 version? 數據庫的版本號 ?*/ super(context,?"user.db",?null,?3); //調用父類的構造方法初始化數據庫,在調用MYOpenHelper才去判斷數據庫是否存在。 } ?/* ??*?onCreate 數據庫第一次創建的時候會被調用?,如果數據庫已經存在,不會被調用。 ??*?SQLiteDatabase 數據庫對象,可以執行SQL語句。 ??*/ @Override public?void?onCreate(SQLiteDatabase?db)?{ //此方法一般用來寫創建表的代碼 db.execSQL("create?table?info?(_id?integer?primary?key?autoincrement,name?varchar(20))"); //注意這里的sql語句是mysql中使用的sql語句的區別,int變成integer,autoincr?????????????????ement中間沒有下劃線 } /* ?*?onUpgrade 當數據庫升級的時候調用。 ?*?oldVersion 新版本 ?*?newVersion 老版本 ?*?注意修改表結構時不能添加重復字段 ?*/ @Override public?void?onUpgrade(SQLiteDatabase?db,?int?oldVersion,?int?newVersion)?{ //此方法一般用來寫修改表結構的代碼 db.execSQL("alter?table?info?add?phone?varchar(11)"); } }
? ?第2步:創建上面定義這個數據庫打開助手類的實例
MyOpenHelper?myOpenHelper?=?new?MyOpenHelper(this);
?? 第3步:利用數據庫打開助手類來創建數據庫(兩種方式)
//getReadableDatabase()方法首先會調用getWritableDatabase()方法,如果數據庫在磁盤中的存儲空間已滿,就會以只讀方式打開數據庫。 SQLiteDatabase?readableDatabase?=?myOpenHelper.getReadableDatabase();????//建議使用 //getWritableDatabase()會以讀寫方式打開數據庫,如果磁盤中的存儲空間已滿,就會直接報錯。 SQLiteDatabase?writableDatabase?=?myOpenHelper.getWritableDatabase();
? 數據庫創建成功后,會生成在/data/data/應用程序包名/databases目錄下,即私有目錄。之前還學過files、shared_prefs目錄。
?3.SQLite增刪改查操作
? ? SQLite的增刪改查的流程是一致的,只是中間執行的sql語句有所不同。
? ?????》通過數據庫助手打開助手返回一個數據庫對象SQLiteDatabase
?????? 》通過SQLiteDatabase對象執行sql語句,2種方式。
????? ?》關閉數據庫。
? ?下面就說上面的第2步操作,執行sql。
? ?*傳統方式:
??????SQLiteDatabase.execSQL("sql語句"[,點位符參數數組Object類型]);
????? 這種方式的弊端就是容易將sql語句寫錯,如有中文字符、圓角字符等;而且execSQL的方法
??????沒有返回值,無法判斷sql操作是否成功。
? ?*調用方法
????? SQLiteDatabase類定義了和sql語句相對應的方法,雖然此方式減小了書寫sql語句出
????? 錯的機率,但是方法的參數比較多,用起來比較麻煩。
? ?????
public?class?UserDaoImpl?implements?UserDao{ private?MyOpenHelper?sqlHelper; //在構造函數中創建SQLiteOpenHelper數據庫打開助手對象 public?UserDaoImpl(Context?context) { sqlHelper?=?new?MyOpenHelper(context); } //增加操作 /* *????insert方法的第3個參數為????ContentValues類型,底層用的是map。存取的是要添加?????????*????的字段的名稱和值。 */ @Override public?long?add(UserBean?user)?{ //得到數據庫對象 SQLiteDatabase?database?=?sqlHelper.getWritableDatabase(); // database.execSQL("insert?into?info?values(null,?,?)",new?Object[]{user.name,user.phone}); //利用SQLiteDatabase自帶的有返回值的方法來替代sql語句。 ContentValues?values?=?new?ContentValues(); values.put("name",?user.name); values.put("phone",?user.phone); long?row_id?=?database.insert("info",?null,?values); database.close(); return?row_id; } //刪除操作 @Override public?long?del(String?name)?{ SQLiteDatabase?database?=?sqlHelper.getWritableDatabase(); // database.execSQL("delete?from?info?where?name?like??",new?Object[]{name}); long?delete_rows?=?database.delete("info",?"name?like??",?new?String[]{name});????//注意條件是沒有where關鍵字的 database.close(); return?delete_rows; } //更新操作 /* *????update方法的第2個參數為????ContentValues類型,底層用的是map。鍵就是要更?????????*????改的字段,值就是修改后的字段對應的值。 */ @Override public?int?update(UserBean?user)?{ SQLiteDatabase?database?=?sqlHelper.getWritableDatabase(); // database.execSQL("update?info?set?name?=??,phone?=??",new?Object[]{user.name?+?"_修改",user.phone?+?"_修改"}); ContentValues?values?=?new?ContentValues(); values.put("phone",?user.phone?+?"_修改"); int?update_rows?=?database.update("info",?values,?"name=?",?new?String[]{user.name}); database.close(); return?update_rows; } //查詢操作 /* *query方法的第2參數為要查詢的項 */ @Override public?List<UserBean>?query()?{ SQLiteDatabase?database?=?sqlHelper.getWritableDatabase(); //創建一個List集合,返回數據 List<UserBean>?list_user?=?new?ArrayList<UserBean>(); //得到查詢集合 //Cursor?cursor?=?database.rawQuery("select?name,phone?from?info",?null); Cursor?cursor?=?database.query("info",?new?String[]{"name","phone"},?null,?null,?null,?null,?null); if(cursor?!=?null?&?cursor.getCount()?>?0) { while(cursor.moveToNext()) { //注意索引是相對于Cursor的,不是相對于數據庫的,第1列為name String?name?=?cursor.getString(0); //得到電話? String?phone?=??cursor.getString(1); list_user.add(new?UserBean(name,phone)); } return?list_user; } return?null; } }
對于Cursor,特別要注意:Cursor得到之后,要調用一次moveToFirst或者moveToNext。否則就會將表頭誤認為表的記錄。?
cursor getCount不為0,但是遍歷卻一個也沒有遍歷出來。
https://www.jianshu.com/p/ba722c2271d6
4.SQLite數據庫的事物?
事務?:?要么多條sql語句同時成功執行,要么同時失敗 銀行轉賬 ????//開啟事物 ????db.beginTransaction(); ????try?{ ????????//??????轉賬 ????????db.execSQL("update?account?set?money=?money-200?where?name=?",new?String[]{"李四"}); ????????db.execSQL("update?account?set?money=?money+200?where?name=?",new?String[]{"張三"}); ????????//設置事物已經成功執行 ????????db.setTransactionSuccessful(); ????}?finally?{ ????????//結束事物 ????????db.endTransaction(); ????}
?5.在linux命令行下執行SQLite數據庫的命令
?
?在多線程訪問數據庫的時候會出現這樣的異常:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.或?java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: 或java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
? ?
?6.數據庫查詢
? ?1)如何從后往前查詢
? ? ?方式1:寫sql語句,用desc關鍵字。
? ? ?方式2:用sqlite自帶的query方法,得到cursor,操作cursor的指針
? ? ?
?List<T>?list; ?boolean?result?=?cursor.moveToLast(); ????if(result){ ????????list.add(result); ????} ?while(cursor.moveToPrevious()){ ?????... ?????list.add(); ?}??? ?return?list;
?
?? 2)查詢指定時間范圍內的數據
? ? ?存儲記錄的時候,存儲一個時間戳,寫sql的時候就好寫了。否則sql語句是不支持自定義的函數的。
??
? 6.Sqlite數據庫的幾大坑要注意:
? ? ?1)database 在app退出的時候記得關掉
? ? ?2)cursor做完查詢后也要關掉
? ?? 3)記得往數據庫存儲的時候用的什么類型,取的時候類型也要對應。特別是在存儲long型時間戳時,定義表用的雖然是Integer類型,但是取的時候還是要
??? ? cursor.getLong來取。
????4)數據庫的結構發生變化 :表的字段發生變化時,一定要寫相關的升級代碼,不要直接跑程序。否則就會發生錯誤。
?????
二、Android中ListView的使用
?1.ListView的使用流程:
? ? ?第1步:創建有ListView的布局,并創建ListView的item項的UI。
????第2步:得到要傳遞給適配器構造函數的數據,可以模擬或從網絡上解析獲取。
????第3步:創建一個適配器對象,一般先會定義一個類繼承BaseAdapter這個抽象適配器類,實現
????? ? ?它的4個基本方法,并創建一個帶有數據參數的構造函數。通過那4個方法將構造函數
????????傳遞初始化的數據參數綁定給lListView的各個item項。
? ? ?第4步:在java代碼中找到ListView,調用它的setAdapter方法關聯創建的適配器對象。
? 2.ListView的代碼實現:?
????以網易新聞客戶端為例,來說明ListView的實現。
????開發步驟:
????第1步:設計UI
????第2步:模擬適配器的數據(實際是從網絡解析的)
????第3步:定義適配器類繼承BaseAdapter類,并創建適配器對象。
????第4步:在java代碼中得到ListView,關聯適配器對象。
????-----------------------------------------------------------------------------
????第1步:設計UI
????????主UI設計:
????
????????子UI設計:
????
????
????第2步:模擬數據
?創建一個bean包,在里面創建一個NewsBean類,定義3?個屬性 ?????class?NewsBean{ ???????????public?Drawablepic;????//代表圖片? ???????????publicString?title,des,url;??//代表主題、內容、鏈接地址??????????????????????? ?????} ?在工具類中創建一個靜態方法,返回List<NewsBean>的集合。
????第3步:定義適配器(最重要、最復雜的一步)*********************************
class?MyAdapter?extends?BaseAdapter { List<NewsBean>?news?=?null; ?//定義構造方法來初始化要綁定給適配器的數據集 public?MyAdapter(List<NewsBean>?news) { this.news?=?news; } ?//getCount返回ListView要顯示的Item條數,一般返回數據集的長度。 @Override public?int?getCount()?{ return?news.size(); } ?????//getItem返回的是指定位置的數據集,并不是item本身。 @Override public?Object?getItem(int?position)?{ return?news.get(position); } ?????//getItemId返回的指定位置item項對應的的id,一般保持與position一致。? @Override public?long?getItemId(int?position)?{ return?position; } ?????//綁定指定位置的item的視圖?? ????@Override public?View?getView(int?position,?View?convertView,?ViewGroup?pare ???????????nt)?{ View?view?=?null; /* ListView的優化,在ListView滾動的時候,不會創建新的view,會引用前面第一 屏創建好的view對象。 */ if(convertView?!=?null) { ????view?=?convertView; }else { ???????????????view?=?View.inflate(mContext,?R.layout.newsitem,?null); ????????/* ????????下面為另外兩種獲取item的view的方式。 ???????????????view?=?LayoutInflater.from(mContext).inflate(R.layout.n ????????????????????????ewsitem,?null); ???LayoutInflater?inflater?=?(LayoutInflater)?mContext.g ????????????????etSystemService(LAYOUT_INFLATER_SERVICE); ???view?=?inflater.inflate(R.layout.newsitem,?null); ?????????*/ } //得到item視圖中的組件 ImageView?imgItem?=?(ImageView)?view.findViewById(R.id.img); TextView?titleItem?=?(TextView)?view.findViewById(R.id.title); TextView?desItem?=?(TextView)?view.findViewById(R.id.des); //獲取指定position的對應于數據集的數據。 NewsBean?newItem?=?news.get(position); //為item組件綁定數據 imgItem.setImageDrawable(newItem.pic); titleItem.setText(newItem.title); desItem.setText(newItem.des); return?view;????//最開始就寫好,不要忘了返回item的顯示視圖。 } }
????第4步:獲取ListView,創建并綁定適配器。
//創建javaBean和適配器 ????????List<NewsBean>?news?=?NewsUtils.getAllNews(mContext); ????????MyAdapter?adapter?=?new?MyAdapter(news); ???????? ?//關聯listView的適配器 ????????ListView?lv_news?=?(ListView)?findViewById(R.id.lv_news); ????????lv_news.setAdapter(adapter);
????最終效果:
????
????▉其它的一些適配器
?????它們都是非抽象類,可以直接用構造函數來傳遞數據并創建對象。
?????■ArrayAdapter
??????它的常用的一個構造方法
????????public ArrayAdapter (Context context, int resource, inttextViewResourceId, T[] objects)
?????????
? ? ????? Parameters
? ? ????? context ???????? 上下文
? ? ? ????resource ? ? ?? ? ? Item項的布局文件R.layout.name
? ? ? ????textViewResourceId ? ??Item項中TextView的id,指的是resource布局中的id. ?????????objects ? ? ? ? ? ?要顯示在item上的數據,有多個數據,就顯示多少
??????????????????????個item。
????????這種適配器比較粗糙,單純的用構造函數來構造的話,也不不能設置Itemview的樣
????????式,而且一個item只能給子布局中的一個TextView適配數據。
??????
????示例代碼及其效果: ???????mContext?=?this; ????????ListView?lv_arr?=?(ListView)findViewById(R.id.lv_arr); ???????? ????????Integer[]?items?=?new?Integer[100]; ????????for(int?i?=?0;?i<items.length;?i++) ????????{ ?????????items[i]?=?i; ????????} ????????ArrayAdapterarrAdapter?=?newArrayAdapter<Object>(mContext,R.layout.item_arradapte ????????????????????????????????r,?R.id.tv_arrItem,?items); ????????lv_arr.setAdapter(arrAdapter);
??????
????效果圖:
????
?????■SimpleAdapter
????????與ArrayAdapter不同,它可以綁定多個TextView的數據,它綁定的數據稍微復雜
????????點。
????? 它的常用構造方法 ?
????????public SimpleAdapter (Context context, List<? extendsMap<String, ?>> data,
????????int resource, String[] from, int[] to)
?
????????Parameters
????????context ??????上下文
????????data ? ? ? ? ? List<?extends Map<String,?>>類型的集合? ??
????????resource ? ? ? ?Item項的布局文件,至少要包含"to"參數中指定的
??????????????????textview,但允許它有其它的組件。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
????????from ? ? ? ? ? map的鍵的名稱數組,它對應的值會被”to”中對應的textview
????????????????? ?顯示?
????????to ?????????顯示"from"數組中map鍵對應的值組件id數組
??? ?示例代碼:
List<Map<String,String>>?data?=?newArrayList<Map<String,String>>(); ????????for(int?i=?0;i?<40;i++) ????????{ ????????????Map<String,String>?map?=?newHashMap<String,String>(); ????????????map.put("name",?"張飛"); ????????????map.put("age",?"30"); ????????????data.add(map); ???????????? ????????????Map<String,String>?map1?=?newHashMap<String,String>(); ????????????map1.put("name",?"李小龍"); ????????????map1.put("age",?"34"); ????????????data.add(map1); ???????????? ????????????Map<String,String>?map2?=?newHashMap<String,String>(); ????????????map2.put("name",?"李連杰"); ????????????map2.put("age",?"50"); ????????????data.add(map2); ????????} ???????? ????????SimpleAdapter?simpleAdapter=?new?SimpleAdapter(mContext,?data,?R.layout.item_simpleadapter,?new?String[]{"name","age"},?newint[]{R.id.tv_name,R.id.tv_age}); ???????? ???????lv_arr.setAdapter(simpleAdapter);
?????效果圖:
????
????
????■SimpleCursorAdapter
? ? ??? ?這個適配器可以綁定數據庫查詢結果集的Cursor對象的數據。
Cursor?cr=?useru.qurryUser1();??????//直接獲得數據庫的數據 SimpleCursorAdapter?adapter?=?newSimpleCursorAdapter(mContext,?R.layout.userinfo_layout,?cr,?new?String[]{"_id","name","phone"},?new?int[]{R.id.tv_id,R.id.tv_name,R.id.tv_phone}); lv_user.setAdapter(adapter);
????說了這么多適配器,其實所有的適配器目的只能一個:為ListView的item指定視圖,為
??ListView中的item視圖中的組件綁定數據。
? ListView就是一個典型的MVC模型
????m:????javabean數據????
????v:????ListView
????c:????Adapter
雜項:
圖片用Drawable類來表示,獲取通過context.getResources().getDrawale(R.drawable.XXX);
注意資源文件不要用中文、數字、大寫字母來命名,否則可能R文件不能正確的自動生成,或不能自動生成。
weight:權重
????width不確定要設置為0,水平等分
????height不確定要設置為0 ?,垂直等分。
4.sqlite3????在/system/xbin
? ? ??
????????
????????
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。