編輯:關於Android編程
上篇博客提到過SQLite,它是嵌入式數據庫,由於其輕巧但功能強大,被廣泛的用於嵌入式設備當中。後來在智能手機、平板流行之後,它作為文件型數據庫,幾乎成為了智能設備單機數據庫的必選,可以隨著安卓app打包到apk文件當中。
SQLite的官方網站是http://www.sqlite.org/,可以任意下載,上面也有詳盡的文檔可以參考,這篇博客重點關注SQLite在Android開發中如何使用。
在Android開發中,推薦建立一個類繼承自SQLiteOpenHelper來創建數據庫操作類,比如:
public class DBHelper extends SQLiteOpenHelper { private static final String database = "test.db"; private static final Integer version = 1; public DBHelper(Context context) { // 構造函數初始化各成員變量 super(context, database, null, version); } @Override public void onCreate(SQLiteDatabase db) { // 當通過SQLiteOpenHelper的子類獲取數據庫連接時,如果數據庫不存在,則調用onCreate方法來創建數據庫 String sql = "create table Score(id integer primary key autoincrement,name varchar(20),point integer)"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 當傳入的實例的數據庫版本號高於之前的版本號時,系統會自動調用onUpgrade方法更新數據庫 // 更新數據庫的操作:備份數據庫表數據,重新創建或修改表、約束等,然後將原來的數據導入到新建的表中。 } }上面的代碼有3點需要注意:
1、構造函數(方法)中指定了數據庫的名稱和版本號
它會默認的在data/data/包名/databases/目錄下創建這個數據庫,當然你也可以指定數據庫文件存在的路徑;版本號設置為1,如果你要想升級,可以在構造方法的參數中加上version,以便初始化。
2、onCreate是在數據庫文件沒有創建的時候執行,如果有了的話則不執行
3、onUpgrade是在新的指定版本號高於舊的指定版本號的時候執行,一般在數據庫升級的時候需要操作
然後我們建一個具體的數據庫操作類:
/** * 成績操作類 * * @author guwei * */ public class ScoreOp { // 插入一條成績記錄 public long insert(SQLiteDatabase db, String name, Integer point) { try { db.beginTransaction(); ContentValues values = new ContentValues(); values.put("name", name); values.put("point", point); long result = db.insert("Score", null, values); if (result != -1) { db.setTransactionSuccessful(); } return result; } finally { db.endTransaction(); } } // 修改一條成績記錄 public int update(SQLiteDatabase db, String name, Integer point) { try { db.beginTransaction(); ContentValues values = new ContentValues(); values.put("name", name); values.put("point", point); int result = db.update("Score", values, "name = ?", new String[] { name }); db.setTransactionSuccessful(); return result; } finally { db.endTransaction(); } } // 刪除一條成績記錄 public long delete(SQLiteDatabase db, String name) { try { db.beginTransaction(); int result = db.delete("Score", "name = ?", new String[] { name }); db.setTransactionSuccessful(); return result; } finally { db.endTransaction(); } } // 查詢根據name正向排序的前10條總分大於指定分數的人員信息 public Cursor query(SQLiteDatabase db, Integer point) { return db.query("Score", new String[] { "name", "sum(point) as points" }, null, null, "name", "sum(point)>=" + point, "name asc", "0,10"); } // 更靈活的查詢,SQL任意拼接 public Cursor query(SQLiteDatabase db, String sql, String[] selectionArgs) { return db.rawQuery(sql, selectionArgs); } }這上面封裝了CRUD操作,而且都是帶事務的(執行多條SQL時需要),值得關注的是最後的兩個query方法。
第一個query是指定了一個復雜sql查詢語句的情況。
按照順序,參數的含義如下:
1)、table The table name to compile the query against.
指定的查詢的表名
2)、columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
返回的查詢列表的列名
3)、selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
where條件,不包括where關鍵字
4)、selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
where條件指定的參數值
5)、groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
group by分組後面跟著的列名
6)、having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
having 後面緊跟著的在分組基礎上進一步篩選的內容
7)、orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
order by後面根據某字段排序
8)、limit Limits the number of rows returned by the query, formatted as LIMIT clause. Passing null denotes no LIMIT clause.
limit關鍵字,分頁查詢時使用
實際上上面對應的這8個參數,就是對應如下SQL查詢語句各關鍵字後面的內容,其原理就是通過指定參數拼接如下SQL語句。
這裡順便提一下,SQLite Expert是非常好用的管理SQLite數據庫的工具,可以在http://www.sqliteexpert.com/下載到,也可以直接搜索下載相應破解版本。
回到第二個query方法,參數很簡單,只有一個sql語句以及一個string數組(提供sql語句參數的值)。這個方法的意義就在於它很靈活,可以直接把能夠執行的sql扔進去執行,而且是參數化的,是第一種查詢方法很有力的補充。
好,最後我們就可以寫測試代碼來驗證了。界面很簡單,直接放置一個按鈕即可。
public class SQLiteActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sqlite); Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DBHelper dbHelper = new DBHelper(SQLiteActivity.this); //獲得一個可寫數據庫操作對象 SQLiteDatabase wdb = dbHelper.getWritableDatabase(); //添加紀錄 ScoreOp scoreOp = new ScoreOp(); scoreOp.insert(wdb, "zhang3", 98); scoreOp.insert(wdb, "zhang3", 94); scoreOp.insert(wdb, "li4", 92); scoreOp.insert(wdb, "wang5", 89); scoreOp.insert(wdb, "wang5", 82); //修改記錄 scoreOp.update(wdb, "li4", 90); //刪除記錄 scoreOp.delete(wdb, "li4"); //獲得一個可讀數據庫操作對象 SQLiteDatabase rdb = dbHelper.getReadableDatabase(); // 1.可以調用系統提供的query方法,以指定參數的形式返回Cursor對象 // Cursor cursor = scoreOp.query(rdb, 192); // 2.可以直接執行SQL查詢語句 Cursor cursor = scoreOp .query(rdb, "select name,sum(point) as points from Score group by name having sum(point)>=192 order by name asc limit ?,?", new String[] { "0", "10" }); while (cursor.moveToNext()) { String name = cursor.getString(cursor .getColumnIndex("name")); Integer points = cursor.getInt(cursor .getColumnIndex("points")); Toast.makeText(SQLiteActivity.this, "姓名:" + name + ";總分:" + points, Toast.LENGTH_SHORT) .show(); } cursor.close(); } }); } }點擊按鈕執行之後就可以彈出符合條件的數據。如果不放心,可以切換到DDMS界面,選擇File Explorer選項卡,找到路徑下的我們創建的test.db文件,Pull(拉取)到電腦磁盤上,用SQLite Expert等工具打開驗證。
1.引言 所謂的消息推送就是從服務器端向移動終端發送連接,傳輸一定的信息。比如一些新聞客戶端,每隔一段時間收到一條或者多條通知,這就是從服務器端傳來的推送消息;還
Android的啟動過程是從init開始的,它是所有後續進程的祖進程。系統啟動的過程可以大致分為以下幾個步驟1,init.c的啟動 掛載目錄 初始化 解析配置文件2
運行時權限介紹Android 6.0在我們原有的AndroidManifest.xml聲明權限的基礎上,又新增了運行時權限動態檢測,以下權限都需要在運行時判斷:身體傳感器
為什麼要使用多線程下載呢?究其原因就一個字:"快",使用多線程下載的速度遠比單線程的下載速度要快,說到下載速度,決定下載速度的因素一般有兩個:一個是客