Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 開發入門 >> Android 開發教程之數據庫連通性

Android 開發教程之數據庫連通性

編輯:開發入門

Android 中一個非常有用的特征就是存在本地關系數據庫。保證您能在本地文件中存儲您的數據,但通常更有用的是使用一個關系型數據庫管理系統(Relational Database Management System,RDBMS)來存儲。Android 提供給您常用的 SQLite 數據庫來進行處理,因為對於像 Android 這類嵌入式系統它是高度優化的。它被 android 上的核心應用程序所用。例如,用戶地址簿是存儲在一個 SQLite 數據庫中。現在,對於給定的 android 的 Java 實現,您可以使用 JDBC 來訪問這些數據庫。出人意料的是,android 甚至包括構成主要部分 JDBC API 的 Java.sql 和 Javax.sql 包。然而,當涉及使用本地 android 數據庫進行處理時,這毫無用處。相反地,您想要使用android.database 和 android.database.sqlite 包。清單 5 是一個使用這些類存儲和檢索數據的示例。


清單 5. 使用 android 進行數據庫訪問 

				
public class StocksDb {
    private static final String DB_NAME = "stocks.db";
    private static final int DB_VERSION = 1;
    private static final String TABLE_NAME = "stock";
    private static final String CREATE_TABLE = "CREATE TABLE " + 
        TABLE_NAME + " (id INTEGER PRIMARY KEY, symbol TEXT, max_price DECIMAL(8,2), " +
            "min_price DECIMAL(8,2), price_paid DECIMAL(8,2), " +
            "quantity INTEGER)";
    private static final String INSERT_SQL = "INSERT INTO " + TABLE_NAME +
            " (symbol, max_price, min_price, price_paid, quantity) " +
            "VALUES (?,?,?,?,?)";
    private static final String READ_SQL = "SELECT id, symbol, max_price, " +
            "min_price, price_paid, quantity FROM " + TABLE_NAME;
    private final Context context;
    private final SQLiteOpenHelper helper;
    private final SQLiteStatement stmt;
    private final SQLiteDatabase db;
    public StocksDb(Context context){
        this.context = context;
        helper = new SQLiteOpenHelper(context, DB_NAME, null, 
                DB_VERSION){
            @Override
            public void onCreate(SQLiteDatabase db) {
                db.execSQL(CREATE_TABLE);
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, 
                    int newVersion) {
                throw new UnsupportedOperationException();
            }
        };
        db = helper.getWritableDatabase();
        stmt = db.compileStatement(INSERT_SQL);
    }
    public Stock addStock(Stock stock){
        stmt.bindString(1, stock.getSymbol());
        stmt.bindDouble(2, stock.getMaxPrice());
        stmt.bindDouble(3, stock.getMinPrice());
        stmt.bindDouble(4, stock.getPricePaid());
        stmt.bindLong(5, stock.getQuantity());
        int id = (int) stmt.executeInsert();
        return new Stock (stock, id);
    }
    public ArrayList<Stock> getStocks() {
        Cursor results = db.rawQuery(READ_SQL, null);
        ArrayList<Stock> stocks = 
                 new ArrayList<Stock>(results.getCount());
        if (results.moveToFirst()){
            int idCol = results.getColumnIndex("id");
            int symbolCol = results.getColumnIndex("symbol");
            int maxCol = results.getColumnIndex("max_price");
            int minCol = results.getColumnIndex("min_price");
            int priceCol = results.getColumnIndex("price_paid");
            int quanitytCol = results.getColumnIndex("quantity");
            do {
                Stock stock = new Stock(results.getString(symbolCol), 
                        results.getDouble(priceCol), 
                        results.getInt(quanitytCol), 
                                    results.getInt(idCol));
                stock.setMaxPrice(results.getDouble(maxCol));
                stock.setMinPrice(results.getDouble(minCol));
                stocks.add(stock);
            } while (results.moveToNext());
        }
        if (!results.isClosed()){
            results.close();
        }
        return stocks;
    }
    public void close(){
        helper.close();
    }    
}

 

清單 5 中的類完全封裝了一個用於存儲股票信息的 SQLite 數據庫。因為您將要使用一個嵌入式數據庫,不僅是您的應用程序要使用它,而且也要通過應用程序來創建它。您需要提供代碼來創建該數據庫。android 提供一個有用的抽象幫助類 SQLiteOpenHelper。要完成這一操作,您需要擴展這個抽象類並提供代碼通過使用 onCreate方法創建您的數據庫。當您有一個幫助程序實例時,就可以獲取一個SQLiteDatabase 實例,您可以用來執行任意 SQL 語句。

您的數據庫類有兩個較為方便的方法。第一個是 addStock,用於將新股票保存到數據庫中。注意,您使用了一個 SQLiteStatement 實例,這類似於一個 Java.sql.PreparedStatement。需要注意的是,在您的類構造器中如何對其進行編譯,使其在每次調用 addStock 時都能重復利用。在每個 addStock 調用中,SQLiteStatement 的變量(INSERT_SQL 字符串中的問號)必然要將數據傳遞給 addStock。再一次強調,這類似於 PreparedStatement ,您可以從 JDBC 了解它。

另一個方法是 getStocks。顧名思義,它從數據庫中檢索所有股票。注意,您再次使用一個 SQL 字符串,正如您在 JDBC 中所用的那樣。您可以在 SQLiteDatabase 類上通過使用 rawQuery 方法來進行處理。這個類也有幾個查詢方法,讓您可以不使用 SQL 直接查詢數據庫。所有這些方法都返回一個 Cursor 對象,和Java.sql.ResultSet 非常相似。您可以將 Cursor 移動到從數據庫中返回的數據所在行,在每一行,您可以使用 getIntgetString和其他的方法來檢索您要查詢的數據庫中各列相關的值。再一次強調,這和 ResultSet 十分相似。也和 ResultSet 比較相似,當您完成操作之後,關閉 Cursor 也十分重要的。如果您沒有關閉Cursors,那麼可能會迅速地耗盡內存並導致您的應用程序崩潰。

查詢本地數據庫是一個比較慢的過程,特別是,如果您有多行數據或者您需要在多個表之間運行復雜的查詢語句。然而,數據庫查詢或插入超過 5 秒且出現一個 Application Not Responding 對話框,這種情況不太可能發生,但是當您的數據庫忙於讀取和寫入數據時,凍結您的 UI 是不明智的。當然,避免這種情況最好的辦法是使用AsyncTask清單 6 展示了這個示例。


清單 6. 在一個單獨的線程上插入數據庫

				
Button button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new OnClickListener(){
    public void onClick(VIEw v) {
        String symbol = symbolIn.getText().toString();
        symbolIn.setText("");
        double max = Double.parseDouble(maxIn.getText().toString());
        maxIn.setText("");
        double min = Double.parseDouble(minIn.getText().toString());
        minIn.setText("");
        double pricePaid = 
                Double.parseDouble(priceIn.getText().toString());
        priceIn.setText("");
        int quantity = Integer.parseInt(quantIn.getText().toString());
        quantIn.setText("");
        Stock stock = new Stock(symbol, pricePaid, quantity);
        stock.setMaxPrice(max);
        stock.setMinPrice(min);
        new AsyncTask<Stock,Void,Stock>(){
            @Override
            protected Stock doInBackground(Stock... newStocks) {
                // There can be only one!
                return db.addStock(newStocks[0]);
            }
            @Override
            protected void onPostExecute(Stock s){
                addStockAndRefresh(s);
            }
        }.execute(stock);
    }
});

 

您可以先為按鈕創建一個實踐監聽器。當用戶點擊按鈕時,您可以從各個小部件(確切地說是 EditText 小部件)讀取股票數據並填入一個新的 Stock 對象。您可以創建一個 AsyncTask,並通過doInBackground 方法從 清單 5 中調用 addStock 方法。如此,addStock 將在一個背景線程上執行,而不是在主 UI 線程上。完成之後,將新 Stock 對象從數據庫傳遞到在主 UI 線程上執行的addStockAndRefresh 方法。


結束語

本文顯示了,即使 Android 在 Java 環境下僅支持眾多 API 的一個子集,但是其功能卻一點都不遜色。在某些示例中,比如網絡,它完全實現了熟悉的 API,也提供了一些更為便捷的方法。在其他的示例中,比如並發性,Android 添加了額外 API 以及一些必須遵循的慣例。最後,在數據庫訪問案例中,android 提供了完全不同的方法來訪問數據庫,但使用的是熟悉的概念。這不僅僅是標准 Java 和 android Java 技術之間主觀上的差異:它們形成了android 開發的基礎構建元件。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved