Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> android開發系列之數據存儲

android開發系列之數據存儲

編輯:Android編程入門

     在我們的android實際開發過程,必不可少的一種行為操作對象就是數據。有些數據,對於用戶而言是一次性的,這就要求我們每次進到App的時候,都需要去刷新數據。有些數據,對於用戶而言又是具有一定時效性的,比如用戶賬號數據。這種情況下,就要求我們采用一定的數據保存措施,在這篇博客裡面,我將為大家分享一些android裡面常用的數據保存方法。

     首先在android裡面我們用的比較多的小數量存儲方式可能就是SharedPreferences,那麼什麼是SharedPreferences呢?為了保存軟件的設置參數,Android 平台為我們提供了一個SharedPreferences 類,它是一個輕量級的存儲類,特別適合用於保存軟件配置參數。使用SharedPreferences 保存數據,其背後是用xml文件存放數據,文件存放在/data/data/<package name>/shared_prefs 目錄下。說白了,它實際上也是一種文件存儲方式。下面讓我們來看看它的具體用法:

public static void openSharep(Context context,String name){
        SharedPreferences sharedPreferences=context.getSharedPreferences(name,Context.MODE_PRIVATE);
        SharedPreferences.Editor editor=sharedPreferences.edit();

        editor.putString("name","hello");
        editor.commit();

    }

 上面是將一個字符串,通過鍵值對的方式存儲到xml文件裡面。這個時候,你也許會問:在什麼情況下,會將SharedPreferences裡面的數據刪掉呢?當我們卸載app的時候,SharePreferences是否還在呢?當我的應用程序更新的時候,SharePreferences文件是否還在呢?我想這有可能跟你當前所使用android系統版本有關系,本人也沒有細查這個問題,如有不對還請留言討論。通過上面的代碼你可能就能夠發現,SharePreferences裡面保存的數據還是相當有限的,主要是一些標識類的數據。

      那麼如果你需要在項目裡面保存大量的數據,你會怎麼辦呢?其實常用的有兩種方式:一種是文件存儲;另外一種就是sqlite數據庫;文件儲存的方式,我們就不做過多的解釋了,直接上代碼,大家肯定就能夠明白了。

String fileName = etFileName.getText().toString();
        String fileContent = etFileContent.getText().toString();
        FileOutputStream out = null;
        try {
            out = context.openFileOutput(fileName, Context.MODE_PRIVATE);
            out.write(fileContent.getBytes("UTF-8"));
            Toast.makeText(this,"保存成功",Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try{
                out.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

 上面的代碼我們直接定義一個輸出流就可以將我們希望保存的信息寫入文件系統裡面了。然後我們再來看看讀取流的代碼:

String fileName=etFileName.getText().toString();
        FileInputStream in=null;
        ByteArrayOutputStream bout=null;
        byte[] buf=new byte[1024];
        bout=new ByteArrayOutputStream();
        int length=0;
        try{
            in=context.openFileInput(fileName);
            while((length=in.read(buf))!=-1){
                bout.write(buf,0,length);
            }
            byte[] content = bout.toByteArray();
            tvInfo.setText(new String(content,"UTF-8")); //設置文本框為讀取的內容
        }catch (Exception e){
            e.printStackTrace();
        }
        tvInfo.invalidate();   //刷新屏幕
        try{
            in.close();
            bout.close();
        }
        catch(Exception e){}

 通過上面的文件操作代碼,我們可以很直觀的發現文件系統無非就是一些中規中矩的文件讀寫操作了。接下來,我們將重點看看數據保存的最重要角色sqlite數據庫。通過數據庫保存下來的文件,我們都知道相對於普通的文件系統具有更好的結構性。就是說我們在操作數據的時候,可以更加有條理性的進行。

      首先讓我們來看看android裡面應該怎樣定義一個數據庫操作對象呢?其實很簡單,我們只需要定義一個類,然後讓它繼承SQLiteOpenHelper就可以了。請看測試類定義:

public class SqliteTest extends SQLiteOpenHelper {

    public SqliteTest(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

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

    }
}

 通過上面的類定義我們可以看到,當我們實現一個構造方法、onCreate、onUpgrade方法之後,我們具有一個數據庫操作的對象了。接下來讓我們首先來完善一下上面SqliteTest類,提供完整的代碼實現:

public class SqliteTest extends SQLiteOpenHelper {

    private static final int VERSION = 1;
    private static final String DB_NAME = "test.db";

    public SqliteTest(Context context) {
        super(context, DB_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS person" +
                "(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, info TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("ALTER TABLE person ADD COLUMN other STRING");
    }
}

        然後當我們拿到這個數據庫操作的對象之後,就應該考慮怎樣使用這個對象了?比如我現在想要往這個數據庫裡面插入一些數據,請看下面的測試代碼:

private SQLiteDatabase db;
private SqliteTest helper;

private void getSqliteDb(){
        db=helper.getWritableDatabase();
    }

    private void addData(List<Person> persons){
        db.beginTransaction();  //開始事務
        try {
            for (Person person : persons) {
                db.execSQL("INSERT INTO person VALUES(null, ?, ?, ?)", new Object[]{person.name, person.age, person.info});
            }
            db.setTransactionSuccessful();  //設置事務成功完成
        } finally {
            db.endTransaction();    //結束事務
        }
    }

 通過上面的代碼我就可以實現數據的插入操作了。

       在這篇博客的最後,讓我們來看看SQLiteOpenHelper類的源碼,探索一下為什麼實現該類之後就能夠進行數據庫操作了呢?我們可以先來看看如下方法:

public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }

 當我們調用getWriteableDatabase方法之後,程序會同步的調用getDatabaseLocked方法:

private SQLiteDatabase getDatabaseLocked(boolean writable) {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // Darn!  The user closed the database by calling mDatabase.close().
                mDatabase = null;
            } else if (!writable || !mDatabase.isReadOnly()) {
                // The database is already open for business.
                return mDatabase;
            }
        }

        if (mIsInitializing) {
            throw new IllegalStateException("getDatabase called recursively");
        }

        SQLiteDatabase db = mDatabase;
        try {
            mIsInitializing = true;

            if (db != null) {
                if (writable && db.isReadOnly()) {
                    db.reopenReadWrite();
                }
            } else if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                try {
                    if (DEBUG_STRICT_READONLY && !writable) {
                        final String path = mContext.getDatabasePath(mName).getPath();
                        db = SQLiteDatabase.openDatabase(path, mFactory,
                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                    } else {
                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                                mFactory, mErrorHandler);
                    }
                } catch (SQLiteException ex) {
                    if (writable) {
                        throw ex;
                    }
                    Log.e(TAG, "Couldn't open " + mName
                            + " for writing (will try read-only):", ex);
                    final String path = mContext.getDatabasePath(mName).getPath();
                    db = SQLiteDatabase.openDatabase(path, mFactory,
                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                }
            }

            onConfigure(db);

            final int version = db.getVersion();
            if (version != mNewVersion) {
                if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }

                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        if (version > mNewVersion) {
                            onDowngrade(db, version, mNewVersion);
                        } else {
                            onUpgrade(db, version, mNewVersion);
                        }
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }

            onOpen(db);

            if (db.isReadOnly()) {
                Log.w(TAG, "Opened " + mName + " in read-only mode");
            }

            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }

 調用這個方法之後系統就能夠給我們提供一個SQLiteDatabase對象,然後我們就可以利用SQLiteDatabase利用的方法進行數據庫操作了。

       至於SQLiteDatabase層的源碼,我自己還沒有怎麼研究過,如有什麼不對的地方,歡迎拍磚!

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