Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android數據存儲詳解

Android數據存儲詳解

編輯:關於Android編程

目錄:
1.概述
2.SQLite
2.1 概述:
2.2 數據類型+存儲位置
2.3 數據操作及其相關方法
2.4 代碼示例
3.SharePreferences
3.1 概述
3.2 操作模式+存儲位置
3.4 代碼示例
4.File
4.1 概述
4.2 操作模式+存儲位置
4.3 手機內存+sdcard保存
5.Content provider
6.網絡存儲

1.概述
數據存儲在App開發和使用中是必不可少的,比如我們會從網絡中保存圖片、視頻等到本地,同時我們的應用在用戶使用過程中會對用戶的行為做一些記錄,以此達到增加用戶體驗的效果,至於保存哪些用戶數據需要由需求而定。
當然我們數據存儲的方式也不止一種,在android平台下包含:SQLite,SharePreferences,File,Content provider,網絡存儲等5種存儲方式,至於選用哪一種存儲方式比較合理,就需要我們在實際開發中綜合考慮,當然,我們在後面也會對每一種存儲方式適合存儲什麼樣的數據做一些簡單的概述。

2.SQLite
2.1 概述:
SQLite屬於輕型嵌入式關系型數據庫,占用資源比較低,應用場景主要在存儲一些需要具備一些保密性,數據量比較大,同時邏輯關系比較復雜的數據,比如:在天氣應用中記錄用戶時區與位置,在鬧鐘應用中存儲一些用戶定義任務等等。

2.2 數據類型+存儲位置
(1)數據類型:NULL,INTEGER(整型),TEXT(字符串文本),REAL(浮點型),BLOB(二進制型)
(2)默認存儲位置:/data/data//databases

2.3 數據操作及其相關方法
(1) 對於數據庫的操作位於android.database.sqlite包下,主要的類有:SQLiteOpenHelper(數據庫幫助類)和SQLiteDatabase(數據庫類),SQLiteOpenHelper類主要用戶數據庫創建於版本管理。而SQLiteDatabase類當然主要用於數據庫的常規操作(增刪改查)和數據庫的維護

(2) SQLiteOpenHelper常用方法
    /*構造方法參數:
    *   1.Context:上下文
    *   2.name:需要創建的數據庫名
    *   3.SQLiteDatabase.CursorFactory:提供創建Cursor對象,默認為null
    *   4.version:數據庫版本
    *   5.errorHandler:數據庫中斷時的錯誤報告處理,null,為默認處理方式
    * */
    public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {}

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

    //返回鏈接的數據庫名
    public String getDatabaseName() {}

    //調用時間:在數據庫需要onDowngrade的時候調用與onUpgrade類似
    //方法在事務中執行,如果出現異常,數據會回滾
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
 
    //數據庫已經被打開的時候調用
    public void onOpen(SQLiteDatabase db) {}

    //在數據庫鏈接正在配置是調用,用於開啟也些相關配置
    public void onConfigure(SQLiteDatabase db) {}
    
    //關閉數據庫鏈接
    public synchronized void close() {}
    
    //獲取一個可讀的數據庫對象
    public SQLiteDatabase getReadableDatabase() {}
    
    //獲取一個可讀寫的數據庫對象
    public SQLiteDatabase getWritableDatabase() {}
    
    //數據庫第一次創建時調用
    public void onCreate(SQLiteDatabase db) {}
    
    //調用時間:在數據庫需要更新的時候調用
    //方法在事務中執行,如果出現異常,數據會回滾                
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}


(3) SQLiteDatabase常用方法

數據庫操作型方法:
        //創建數據庫,該數據庫在關閉之後數據將消失
        public static SQLiteDatabase create(CursorFactory factory) {}
        
        //打開或者創建指定文件路徑的數據庫
        public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) {}
        
        //打開指定文件路徑的數據庫
        public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {}
        
        //刪除指定路徑的數據庫
        public static boolean deleteDatabase(File file) {}

數據表與數據處理型方法:
        //執行sql語句,可實現增刪改查,與表的創建,刪除
        public void execSQL(String sql, Object[] bindArgs) throws SQLException {}
        public void execSQL(String sql) throws SQLException {}
        
        //刪除指定數據
        public int delete(String table, String whereClause, String[] whereArgs) {}
        
        //查詢數據
         public Cursor query(boolean distinct, String table, String[] columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit) {}
            
        //執行已定義的sql語句,返回結果Cursor
        public Cursor rawQuery(String sql, String[] selectionArgs) {}
        
        //插入數據
        public long insert(String table, String nullColumnHack, ContentValues values) {}
        
        //更新數據
         public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {}

事務處理型方法:
        //表示事務執行成功
        public void setTransactionSuccessful() {}
        //結束某個事務
        public void endTransaction() {}
        //開啟事務
        private void beginTransaction(){}

2.4 代碼示例
(1) MySqliteOpenHelper.java
package com.example.database;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Created by elimy on 2016-09-03.
 */
public class MySqliteOpenHelper extends SQLiteOpenHelper {
    private final String DEBUG ="DEBUG";

    //如果數據庫名和版本固定,不需要改變可以如下設置,調用時只需要傳入上下文即可
    private static final String DEFULT_DB_NAME ="first.db";
    private static final int DEFULT_VERSION = 1;
    public MySqliteOpenHelper(Context context) {
        super(context, DEFULT_DB_NAME, null, DEFULT_VERSION);
    }

    /*構造方法參數:
    *   1.Context:上下文
    *   2.name:需要創建的數據庫名
    *   3.SQLiteDatabase.CursorFactory:提供創建Cursor對象,默認為null
    *   4.version:數據庫版本
    *   5.errorHandler:數據庫中斷時的錯誤報告處理,null,為默認處理方式
    * */
    public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

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

    /*
    * 作用:返回鏈接的數據庫名
    * */
    @Override
    public String getDatabaseName() {
        return super.getDatabaseName();
    }

    /*
    *調用時間:在數據庫需要onDowngrade的時候調用與onUpgrade類似
    * 方法在事務中執行,如果出現異常,數據會回滾
    * */
    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(DEBUG,"onDowngrade()");
        super.onDowngrade(db, oldVersion, newVersion);
    }
    /*
    *調用時間:數據庫已經被打開的時候調用
    * */
    @Override
    public void onOpen(SQLiteDatabase db) {
        Log.d(DEBUG,"onOpen()");
        super.onOpen(db);
    }

    /*
    *在數據庫鏈接正在配置是調用,用於開啟也些相關配置
    * */
    @Override
    public void onConfigure(SQLiteDatabase db) {
        Log.d(DEBUG,"onConfigure()");
        super.onConfigure(db);
    }
    /*
    *關閉數據庫鏈接
    * */
    @Override
    public synchronized void close() {
        Log.d(DEBUG,"close()");
        super.close();
    }
    /*
    * 獲取一個可讀的數據庫對象
    * */
    @Override
    public SQLiteDatabase getReadableDatabase() {
        Log.d(DEBUG,"getReadableDatabase()");
        return super.getReadableDatabase();
    }
    /*
    * 獲取一個可讀寫的數據庫對象
    * */
    @Override
    public SQLiteDatabase getWritableDatabase() {
        Log.d(DEBUG,"getWritableDatabase()");
        return super.getWritableDatabase();
    }
    /*
    * 數據庫第一次創建時調用
    * */
    @Override
    public void onCreate(SQLiteDatabase db) {
        //創建數據表users
        db.execSQL("create table users(" +
                "u_id INTEGER primary key autoincrement," +
                "u_name TEXT," +
                "u_password TEXT," +
                "u_sex TEXT," +
                "u_age INTEGER)");
        Log.d(DEBUG,"onCreate()");
    }
    /*
    *調用時間:在數據庫需要更新的時候調用
    * 方法在事務中執行,如果出現異常,數據會回滾
    * */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(DEBUG,"onUpgrade()");
    }
}

(2) SqliteActivity.java
package com.example.database;

import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class SqliteActivity extends AppCompatActivity implements View.OnClickListener {
    private Button add,update,delete,select;
    private MySqliteOpenHelper helper;
    private SQLiteDatabase db;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite);
        //初始化數據
        add = (Button) findViewById(R.id.add);
        update = (Button) findViewById(R.id.update);
        select = (Button) findViewById(R.id.select);
        delete = (Button) findViewById(R.id.delete);
        //注冊監聽器
        add.setOnClickListener(this);
        update.setOnClickListener(this);
        select.setOnClickListener(this);
        delete.setOnClickListener(this);

        //通過MySqliteOpenHelper的帶一個參數構造函數,初始化helper對象
        helper = new MySqliteOpenHelper(SqliteActivity.this);
    }

    public  void insertData(){
        //開啟一個可寫的數據庫對象
        db = helper.getWritableDatabase();
        //插入數據集(鍵值對)初始化
        ContentValues values = new ContentValues();
        values.put("u_name","Elimy");
        values.put("u_password","456");
        values.put("u_sex","男");
        values.put("u_age",26);
        //插入數據
        //table:表名, nullColumnHack:如果可為空的字段未賦值則設置為空,
        // ContentValues:數據集
        long back = db.insert("users",null,values);
        if (back !=-1){
            Toast.makeText(SqliteActivity.this,"添加成功",Toast.LENGTH_SHORT).show();
            Log.d("add","添加成功");
        }else {
            Log.d("add","添加失敗");
        }
        //釋放數據庫連接對象
        db.close();
    }
    /*
    * 更新數據
    * */
    public  void updateData(){
        //開啟一個可寫的數據庫對象
        db = helper.getWritableDatabase();
        //插入數據集(鍵值對)初始化
        ContentValues values = new ContentValues();
        values.put("u_name","Andy");
        values.put("u_password","789");
        values.put("u_sex","女");
        values.put("u_age",26);
        //更新數據
        long back = db.update("users",values,"u_id=?",new String[]{"1"});
        if (back !=0){
            Toast.makeText(SqliteActivity.this,"修改成功",Toast.LENGTH_SHORT).show();
            Log.d("update","修改成功");
        }else {
            Log.d("update","修改失敗");
        }
        //釋放數據庫連接對象
        db.close();
    }
    /*
    * 查詢數據
    * */
    public  void selectData(){
        //開啟一個可寫的數據庫對象
        db = helper.getReadableDatabase();
        //查詢
        Cursor cursor = db.query("users",new String[]{"u_name","u_password","u_sex","u_age"},null,null,null,null,null);
        while (cursor.moveToNext()){
            Log.d("users",cursor.getString(cursor.getColumnIndex("u_name"))+"+"+cursor.getString(cursor.getColumnIndex("u_password"))+"+"+cursor.getString(cursor.getColumnIndex("u_sex"))+"+"+cursor.getString(cursor.getColumnIndex("u_age")));
        }
        //釋放數據庫連接對象
        db.close();
    }
    /*
    * 刪除數據
    * */
    public  void deleteData(){
        //開啟一個可寫的數據庫對象
        db = helper.getWritableDatabase();
        //刪除數據
        int back = db.delete("users","u_id=?",new String[]{"1"});
        if (back == 0){
            Log.d("delete","刪除失敗");
        }else {
            Log.d("delete","刪除成功");
        }
        //釋放數據庫連接對象
        db.close();
    }
    /*
    * 點擊事件監聽方法
    * */
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.add :
                insertData();
                break;
            case R.id.update:
                updateData();
                break;
            case R.id.select:
                selectData();
                break;
            case R.id.delete:
                deleteData();
                break;
            default:
                break;
        }
    }
}

(3) activity_sqlite.xml


(4) 操作和相應的Log打印(ps:之前添加過一條)
添加數據:
    09-03 08:39:37.976 9594-9594/? D/DEBUG: getWritableDatabase()
    09-03 08:39:37.980 9594-9594/? D/DEBUG: onConfigure()
    09-03 08:39:37.980 9594-9594/? D/DEBUG: onOpen()
    09-03 08:39:37.992 9594-9594/? D/add: 添加成功

修改數據:
    09-03 08:40:45.972 9594-9594/? D/DEBUG: getWritableDatabase()
    09-03 08:40:45.972 9594-9594/? D/DEBUG: onConfigure()
    09-03 08:40:45.972 9594-9594/? D/DEBUG: onOpen()
    09-03 08:40:45.980 9594-9594/? D/update: 修改成功

查詢數據:
    09-03 08:42:22.672 9594-9594/? D/DEBUG: getReadableDatabase()
    09-03 08:42:22.676 9594-9594/? D/DEBUG: onConfigure()
    09-03 08:42:22.676 9594-9594/? D/DEBUG: onOpen()
    09-03 08:42:22.676 9594-9594/? D/users: Andy+789+女+26
    09-03 08:42:22.676 9594-9594/? D/users: Elimy+456+男+26

刪除數據+查詢數據:
    09-03 08:43:17.040 9594-9594/? D/DEBUG: getWritableDatabase()
    09-03 08:43:17.040 9594-9594/? D/DEBUG: onConfigure()
    09-03 08:43:17.044 9594-9594/? D/DEBUG: onOpen()
    09-03 08:43:17.052 9594-9594/? D/delete: 刪除成功
    09-03 08:43:23.084 416-565/system_process W/ThrottleService: unable to find stats for iface rmnet0
    09-03 08:43:23.496 9594-9594/? D/DEBUG: getReadableDatabase()
    09-03 08:43:23.496 9594-9594/? D/DEBUG: onConfigure()
    09-03 08:43:23.496 9594-9594/? D/DEBUG: onOpen()
    09-03 08:43:23.496 9594-9594/? D/users: Elimy+456+男+26

3.SharePreferences
3.1 概述
SharePreferences是一種輕量級的存儲數據方式,以xml鍵值對的形式存儲數據,應用場景主要是存儲應用的配置信息

3.2 操作模式+存儲位置
(1)操作模式:
MODE_PRIVATE:文件僅應用程序自己能訪問。

MODE_WORLD_READABLE:文件除了自己訪問外還可以被其它應該程序讀取(推薦使用Content provider)

MODE_WORLD_WRITEABLE:文件除了自己訪問外還可以被其它應該程序讀取和寫入(推薦使用Content provider)

MODE_APPEND:在文件尾部追加

(2)默認存儲位置:/data/data//shared_prefs

3.4 代碼示例(實現登陸功能,將用戶名、密碼以及是否保存密碼數據保存到SharePreferences文件中,當然實際開發為了賬戶安全
需慎重使用)

(1) MainActivity.java
package com.example.sharepreferences;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText edit_userNmae,edit_password;
    private Button cancel,login,read;
    private CheckBox save;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        edit_userNmae = (EditText) findViewById(R.id.editText_name);
        edit_password = (EditText) findViewById(R.id.editText_pas);
        cancel = (Button) findViewById(R.id.cancel);
        login = (Button) findViewById(R.id.login);
        save = (CheckBox) findViewById(R.id.check);
        read = (Button) findViewById(R.id.read);
        //注冊監聽
        cancel.setOnClickListener(this);
        login.setOnClickListener(this);
        read.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.cancel:
                Toast.makeText(MainActivity.this,"取消登錄",Toast.LENGTH_SHORT).show();
                break;
            case R.id.login:
                //獲取用戶輸入數據
                String user_name = edit_userNmae.getText().toString().trim();
                String password = edit_password.getText().toString().trim();
                Boolean isSavePas = save.isChecked();
                //創建SharedPreferences對象,默認以應用程序包名為文件名
                // SharedPreferences preferences = getPreferences(MODE_PRIVATE);
                SharedPreferences preferences = getSharedPreferences("info",this.MODE_PRIVATE);
                //PreferenceManager實例化,默認以應用程序包名為文件名
                //SharedPreferences preferences2 = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
                //獲取編輯類實例
                SharedPreferences.Editor editor = preferences.edit();
                //put數據
                editor.putString("username",user_name);
                editor.putString("password",password);
                editor.putBoolean("isSavePas",isSavePas);
                //提交事務
                editor.commit();
                break;
            case R.id.read:
                //聲明並初始化SharedPreferences
                SharedPreferences backPreferences = getSharedPreferences("info",this.MODE_PRIVATE);
                //獲取preference中的數據
                String backName = backPreferences.getString("username","");
                String backPassword = backPreferences.getString("password","");
                Boolean backChecked = backPreferences.getBoolean("isSavePas",false);
                //打印顯示
                Log.d("back",backName+"+"+backPassword+"+"+backChecked);
                break;
            default:
                break;
        }
    }
}

(2) activity_main.xml


    

    

    

    

    
    

    

    

(3) 效果截圖
\

(4) Log打印(點擊登陸,再點擊讀取數據)
    09-03 13:21:30.503 3745-3745/com.example.sharepreferences D/back: elimy+456+true

(5) DDMS查看手機文件截圖
\

4.File
4.1 概述
File文件存儲,在android應用做,我們除了一些簡單的數據和關系型數據需要通過Sharepreference和sqlite存儲以外,通常
還有大數據型文件存儲的需求,比如文本文件、圖片文件、視頻文件等,這時候File文件存儲就比較符合需求,當然默認存儲位置在手機
內存中,由於內存有限,大多數情況會有存儲到sdcard的需求。

4.2 操作模式+存儲位置
MODE_PRIVATE:文件僅應用程序自己能訪問(默認)。

MODE_WORLD_READABLE:文件除了自己訪問外還可以被其它應該程序讀取(推薦使用Content provider)

MODE_WORLD_WRITEABLE:文件除了自己訪問外還可以被其它應該程序讀取和寫入(推薦使用Content provider)

MODE_APPEND:在文件尾部追加

(2)默認存儲位置:/data/data//files

4.3 手機內存+sdcard保存文件

(1)MainActivity.java
package com.example.file;

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText editTitle,editContent;
    private Button savePhone,saveSD;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        editTitle = (EditText) findViewById(R.id.edit_title);
        editContent = (EditText) findViewById(R.id.edit_content);
        savePhone = (Button) findViewById(R.id.phone_save);
        saveSD = (Button) findViewById(R.id.sdcard_save);
        //注冊監聽
        savePhone.setOnClickListener(this);
        saveSD.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //獲取用戶輸入數據
        String title = editTitle.getText().toString().trim();
        String content = editContent.getText().toString().trim();
        switch (v.getId()){
            case R.id.phone_save:
                if (title != null && content!= null){
                    try {
                        //通過文件輸出流寫入文件到手機內存
                        //聲明並初始化FileOutputStream
                        //參數:
                        //    name:文件名
                        //    mode:操作模式
                        FileOutputStream fos =this.openFileOutput("test.txt", Context.MODE_APPEND);
                        //寫入title
                        fos.write(title.getBytes());
                        //寫入換行符
                        fos.write("\n".getBytes());
                        //寫入coontent
                        fos.write(content.getBytes());
                        //關閉文件流
                        fos.close();
                        Toast.makeText(MainActivity.this,"保存到手機默認地址成功!",Toast.LENGTH_SHORT).show();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else {
                    Toast.makeText(MainActivity.this,"請填寫內容再保存!",Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.sdcard_save:
                if (title !=null && content!= null){
                       //判斷sdcard是否掛載
                        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                          //獲取sdcard根目錄
                            File sdcard_dir = Environment.getExternalStorageDirectory();
                            Log.d("sdcard_dir",sdcard_dir.toString());
                            //實例化saveFile
                            File saveFile = new File(sdcard_dir,"test.txt");

                            try {
                                //實例化指向目的文件位置的FileOutputStream
                                FileOutputStream fos=new FileOutputStream(saveFile,true);
                                //寫入內容
                                fos.write(title.getBytes());
                                fos.write("\n".getBytes());
                                fos.write(content.getBytes());
                                //關閉文件流
                                fos.close();
                                Toast.makeText(MainActivity.this,"保存sdcard成功!",Toast.LENGTH_SHORT).show();
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                }else {
                    Toast.makeText(MainActivity.this,"請填寫內容再保存!",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }
}

(2)布局activity_main.xml





    
    


    
    


(3)訪問sdcard需要注冊權限
    
    
    
    

(4))手機內存和sdcard保存文件效果圖+驗證截圖

\ \ (1)布局效果圖 (2)sdcard驗證保存成功截圖


\

(3) 手機內存查看驗證截圖

5.Content provider
Content provider也被封為四大組件之一,是一種應用之間提供數據共享的機制,其實他的存儲方式也是通過數據庫或者其他存儲方式實現的,他只是提供一個共外界訪問的接口,方便外界訪問而已。之前我寫一篇關於Content provider的文章,這裡又不做總結了。

6.網絡存儲
所謂的網絡存儲也就是通過網絡請求獲取數據,後面在網絡部分進行學習,在此暫時就不學習了。

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