【073】Android 数据存储(SQLite)

目录:

I. 使用 SharedPreferences 来存储应用程序的数据

II. 将应用程序的数据存储到内部存储器中

III. 将应用程序的数据存储到外部存储器中

IV. 通过 SQLite 数据库来实现数据存储

V. Content Provider 简介


I. 使用 SharedPreferences 来存储应用程序的数据:

参考:Beginning Android 4 Application Development - Page 252

  • 将数据存储到 SharedPreferences 对象中去,这个时候要用到 SharedPreferences.Editor 中的方法。
  • 上面的过程会将数据存储在一个 xml 文件中。
      在 DDMS 视图中找到 File Explore, 选择 data/data/<PackageName>/shared_prefs/*.xml

      如下图所示:
      
  • 通过 getSharedPreferences() 方法获取 SharedPreferences 对象,并将里面的数据取出。

举例效果:

代码功能:通过"修改文本"按钮可以将文本内容存储, 然后点击"显示文本"按钮就可以显示出刚才修改了的文本.

另外:在其他的 activity 中也可以直接的调用, 调用方法与下面的一样~

 1 public class MainActivity extends Activity {
 2 
 3     @Override
 4     public void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7         
 8         Button displayButton = (Button)findViewById(R.id.button1);
 9         displayButton.setOnClickListener(new OnClickListener() {
10             
11             public void onClick(View v) {
12                 // TODO Auto-generated method stub
13                 SharedPreferences appPreferences = getSharedPreferences(
14                         "com.example.preferenceexer_preferences", MODE_PRIVATE);
15                 Toast.makeText(MainActivity.this, appPreferences.getString("editTextPref", ""), Toast.LENGTH_SHORT).show();
16             }
17         });
18         
19         Button modifyButton = (Button)findViewById(R.id.button2);
20         modifyButton.setOnClickListener(new OnClickListener() {
21             
22             public void onClick(View v) {
23                 // TODO Auto-generated method stub
24                 SharedPreferences appPreferences = getSharedPreferences(
25                         "com.example.preferenceexer_preferences", MODE_PRIVATE);
26                 SharedPreferences.Editor prefsEditor = appPreferences.edit();
27                 prefsEditor.putString("editTextPref", ((EditText)findViewById(R.id.editText1)).getText().toString());
28                 prefsEditor.commit();
29             }
30         });
31     }
32 }

SharedPreferences 接口

1. Interface for accessing and modifying preference data returned by getSharedPreferences(String, int).

  getSharedPreferences(String, int):返回值:SharedPreferences
    第一个参数:就是存储文件的名称, 一般以 <PackageName>_preferences 的格式, 其他应该也是可以的
    第二个参数:0 代表 MODE_PRIVATE, 只允许此程序使用. 还有其他的常量.

2. SharedPreferences Methods:

  • edit():返回值:SharedPreferences.Editor. 进入编辑模式.
  • contains(String key):检查是否存在指定的键.
  • getAll():返回值:Map<String, ?>. 从 preferences 中取回所有的值.

  • getBoolean(String key, boolean defValue):取回布尔值, 第二个为参数默认值.
  • getFloat(String key, float defValue):
  • getInt(String key, int defValue):
  • getLong(String key, long defValue):
  • getString(String key, String defValue):取回字符串, 第二个参数为默认值.
  • getStringSet(String key, Set<String> defValues):

SharedPreferences.Editor 接口

1. 用来修改 SharedPreferences 对象的值。

2. SharedPreferences.Editor Methods:

  • commit():提交修改的内容.
  • apply():同上.
  • remove(String key):删除指定的键.
  • clear():全部清空.

  • putBoolean(String key, boolean value):加入布尔值.
  • putFloat(String key, float value):
  • putInt(String key, int value):
  • putLong(String key, long value):
  • putString(String key, String value):加入字符串.
  • putStringSet(String key, Set<String> values):

 


II. 将应用程序的数据存储到内部存储器中:

参考:Beginning Android 4 Application Development - Page 263

效果图:

 

在 DDMS 视图中找到 File Explore, 选择 data/data/<PackageName>/files/textfile.txt
  如下图所示: 

public class FilesActivity extends Activity {
    EditText textBox;
    static final int READ_BLOCK_SIZE = 100;  //字符数组

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textBox = (EditText) findViewById(R.id.txtText1);
    }

    public void onClickSave(View view) {
        String str = textBox.getText().toString();
        try
        {  
            FileOutputStream fOut = openFileOutput("textfile.txt", MODE_WORLD_READABLE);  //文件输出流
            OutputStreamWriter osw = new OutputStreamWriter(fOut);
            osw.write(str);
            osw.close();
            Toast.makeText(getBaseContext(), "File saved successfully!", Toast.LENGTH_SHORT).show();
            textBox.setText("");
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
    }

    public void onClickLoad(View view) {
        try
        {
            FileInputStream fIn = openFileInput("textfile.txt");  //文件写入流
            InputStreamReader isr = new InputStreamReader(fIn);
            
            char[] inputBuffer = new char[READ_BLOCK_SIZE];
            String s = "";
            int charRead;
            while ((charRead = isr.read(inputBuffer))>0)
            {
                String readString = String.copyValueOf(inputBuffer, 0, charRead);
                s += readString;
                inputBuffer = new char[READ_BLOCK_SIZE];
            }
            textBox.setText(s);
            Toast.makeText(getBaseContext(), "File loaded successfully!", Toast.LENGTH_SHORT).show();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

源文件下载:Files.zip

 


III. 将应用程序的数据存储到外部存储器中:

参考:Beginning Android 4 Application Development - Page 268

效果图:

 

在 DDMS 视图中找到 File Explore, 选择 mnt/sdcard/MyFiles/textfile.txt
  如下图所示:

public class FilesActivity extends Activity {
    EditText textBox;
    static final int READ_BLOCK_SIZE = 100;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textBox = (EditText) findViewById(R.id.txtText1);
    }

    public void onClickSave(View view) {
        String str = textBox.getText().toString();
        try
        {
            //---SD Card Storage---
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File (sdCard, "MyFiles");
            directory.mkdirs();
            File file = new File(directory, "textfile.txt");
            FileOutputStream fOut = new FileOutputStream(file);

            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(str);
            bufferedWriter.close();
            Toast.makeText(getBaseContext(), "File saved successfully!", Toast.LENGTH_SHORT).show();
            textBox.setText("");
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
    }

    public void onClickLoad(View view) {
        try
        {
            //---SD Storage---
            File sdCard = Environment.getExternalStorageDirectory();
            File directory = new File (sdCard.getAbsolutePath() + 
                "/MyFiles");
            File file = new File(directory, "textfile.txt");
            FileInputStream fIn = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fIn);

            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            char[] inputBuffer = new char[100];
            String strSum = "";
            int charRead;
            while ((charRead = bufferedReader.read(inputBuffer)) > 0) {
                strSum += new String(inputBuffer);
            }
            bufferedReader.close();
            textBox.setText(strSum);
            Toast.makeText(getBaseContext(), "File loaded successfully!", Toast.LENGTH_SHORT).show();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

源文件下载:Files.zip 

 


IV. 通过 SQLite 数据库来实现数据存储:

参考:Beginning Android 4 Application Development - Page 273

※ 参考:Android之SQlite存储


☀-☀ → SQLiteDatabase 类

1. 显示了一些用来管理 SQLite 数据的方法。

java.lang.Object
   ↳    android.database.sqlite.SQLiteClosable
        ↳    android.database.sqlite.SQLiteDatabase

2. 方法:

  • execSQL(String sql):执行没有返回结果的 SQL 语句.
  • insert(String table, String nullColumnHack, ContentValues values):插入数据. 返回 ID 值(long).
      第一个参数:欲插入行的表的名称.
      第二个参数:直接 null.
      第三个参数:包括了初始化行值的 map. key 对应列名称, value 对应列的值.
        ContentValues:通过 ContentValues 的 put() 方法可以键值对添加进去.
  • delete(String table, String whereClause, String[] whereArgs):删除数据. 返回值表示删除的个数(int).
      第二个参数:WHERE 语句内容, null 将删除所有列.
      第三个参数:null.
  • update(String table, ContentValues values, String whereClause, String[] whereArgs):更新数据. 返回值为受影响的行数(int).
  • rawQuery(String sql, String[] selectionArgs):返回值:Cursor.
      第一个参数:SQL 查询语句, 语句结尾要有分号";"结束.
     
  • query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy):查询, 返回值:Cursor.
      第一个参数:欲查询的表名称.
      第二个参数:想要得到返回值的列的 list. 传递 null 则返回所有列. 
      第三个参数:类似一个 SQL WHERE 语句(不包括关键字, 下面一样), null 则返回所有的行.
      第四个参数:用来替换文本的, 就给个 null 好了.
      第五个参数:SQL GROUP BY 语句, null 则不排序.
      第六个参数:SQL HAVING 语句, 不用就 null.
      第七个参数:SQL ORDER BY 语句, 不用就 null. 
  • query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit):
      第八个参数:LIMIT 语句. 限制返回查询的行的个数.
  • query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit):
      第一个参数:true 则返回的每一行是惟一的, 否则为 false.

 


☀-☀ →Cursor 接口

1. 数据库查询指针.

若想通过 Cursor 来遍历所有数据, 首先要调用 moveToFirst() 方法, 因为指针不一定知道最上面的位置, 否则会出现数据遗漏, 同时也可以使用 moveToLast() 方法, 然后往上移动~

  当调用 moveToFirst() 方法的时候, 显示此时 getPosition() 返回值为 0, 也就是第一条记录;
  当调用 moveToLast() 方法的时候, 显示此时 getPosition() 返回值为 7, 也就是最后一条记录.

android.database.Cursor

2. 方法:

  • getColumnCount():获取所有列数.
  • getColumnIndex(String columnName):通过列名称查找列索引.
  • getColumnName(int columnIndex):
  • getColumnNames():返回值:String[]. 返回所有列名的数组.
  • getCount():返回所有的行数.
  • getPosition():返回当前位于此行集合中的位置.

  • getExtras():返回值:Bundle.
  • getDouble(int columnIndex):
  • getFloat(int columnIndex):
  • getInt(int columnIndex):
  • getLong(int columnIndex):
  • getShort(int columnIndex):
  • getString(int columnIndex):
  • getType(int columnIndex):

  • isBeforeFirst():返回是否现在指针指在第一行之前.
  • isAfterLast():返回是否现在指针指在最后一行之后.
  • isFirst():返回指针是否指在第一行.
  • isLast():返回指针是否指在最后一行.
  • isNull(int columnIndex):返回指定列是否为空.
  • isClosed():返回此指针是否关闭.

  • move(int offset):指针从当前位置向前或向后移动一定的行数.
  • moveToFirst():将指针移动到第一行.
  • moveToLast():将指针移动到最后一行.
  • moveToPrevious():将指针向前移动一行.
  • moveToNext():将指针向后移动一行.
  • moveToPosition(int position):将指针移动到指定的行位置.

 


☀-☀ → SQLiteOpenHelper 类

1. 用于数据库创建和版本管理的帮助类.

java.lang.Object
   ↳    android.database.sqlite.SQLiteOpenHelper

2. 方法:

  • close():关闭任何打开的数据库对象.
  • getDatabaseName():返回正在运行的 SQLite 数据库的名称.
  • getReadableDatabase():返回值:SQLiteDatabase. 创建 和/或 打开一个数据库.
  • getWritableDatabase():返回值:SQLiteDatabase. 创建 和/或 打开一个数据库, 这个数据库将被读和写.

  • onOpen(SQLiteDatabase db):当数据库运行的时候执行.
  • onCreate(SQLiteDatabase db):当数据库第一次创建的时候执行.
  • onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库需要升级的时候执行.

 


效果展示:

数据库被默认存储在 data/data/<Package_Name>/databases 文件夹内部:

MyDB 中显示的内容如下:

第一步:新建一个 DBAdapter 类, 写入操作数据库的各种方法.

public class DBAdapter {
    static final String KEY_ROWID = "_id";
    static final String KEY_NAME = "name";
    static final String KEY_EMAIL = "email";
    static final String TAG = "DBAdapter";

    static final String DATABASE_NAME = "MyDB";
    static final String DATABASE_TABLE = "contacts";
    static final int DATABASE_VERSION = 2;

    static final String DATABASE_CREATE =
        "create table contacts (_id integer primary key autoincrement, "
        + "name text not null, email text not null);";

    final Context context;

    DatabaseHelper DBHelper;
    SQLiteDatabase db;
    
    public DBAdapter(Context ctx)
    {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }

    private static class DatabaseHelper extends SQLiteOpenHelper
    {
        DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);  //新建数据库文件
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            try {
                db.execSQL(DATABASE_CREATE);  //创建数据库表
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS contacts");
            onCreate(db);
        }
    }

    //---opens the database---
    public DBAdapter open() throws SQLException 
    {
        db = DBHelper.getWritableDatabase();  //为 SQLiteDatabase 赋值.
        return this;
    }

    //---closes the database---
    public void close() 
    {
        DBHelper.close();
    }

    //---insert a contact into the database---
    public long insertContact(String name, String email) 
    {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_NAME, name);
        initialValues.put(KEY_EMAIL, email);
        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    //---deletes a particular contact---
    public boolean deleteContact(long rowId) 
    {
        return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
    }

    //---retrieves all the contacts---
    public Cursor getAllContacts()
    {
        return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
                KEY_EMAIL}, null, null, null, null, null);
    }

    //---retrieves a particular contact---
    public Cursor getContact(long rowId) throws SQLException 
    {
        Cursor mCursor =
                db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
                KEY_NAME, KEY_EMAIL}, KEY_ROWID + "=" + rowId, null,
                null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }

    //---updates a contact---
    public boolean updateContact(long rowId, String name, String email) 
    {
        ContentValues args = new ContentValues();
        args.put(KEY_NAME, name);
        args.put(KEY_EMAIL, email);
        return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
    }
}

第二步:在 activity 中调用.

public class DatabasesActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DBAdapter db = new DBAdapter(this);

  //下面实现文件从 assets 文件夹中赋值到指定的程序目录中去. try { String destPath = "/data/data/" + getPackageName() + "/databases"; File f = new File(destPath); if (!f.exists()) { f.mkdirs(); f.createNewFile(); //---copy the db from the assets folder into // the databases folder--- CopyDB(getBaseContext().getAssets().open("mydb"), new FileOutputStream(destPath + "/MyDB")); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //---get all contacts--- db.open(); Cursor c = db.getAllContacts(); if (c.moveToFirst()) { do { DisplayContact(c); } while (c.moveToNext()); } db.close(); } public void CopyDB(InputStream inputStream, OutputStream outputStream) throws IOException { //---copy 1K bytes at a time--- byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } inputStream.close(); outputStream.close(); } public void DisplayContact(Cursor c) { Toast.makeText(this, "id: " + c.getString(0) + "\n" + "Name: " + c.getString(1) + "\n" + "Email: " + c.getString(2), Toast.LENGTH_LONG).show(); } }

源文件下载: Databases.zip

下面展示一些常用操作的实现代码:

  INSERT - 插入数据

public long insertContact(String name, String email) 
{
    ContentValues initialValues = new ContentValues();
    initialValues.put(KEY_NAME, name);
    initialValues.put(KEY_EMAIL, email);
    return db.insert(DATABASE_TABLE, null, initialValues);
}
//---add a contact---
db.open();
long id = db.insertContact("Wei-Meng Lee", "weimenglee@learn2develop.net");
id = db.insertContact("Mary Jackson", "mary@jackson.com");
db.close();

  SELECT - 选择语句

public Cursor getAllContacts()
{
    return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
            KEY_EMAIL}, null, null, null, null, null);  //null 为返回全部.
}
//--get all contacts---
db.open();
Cursor c = db.getAllContacts();
if (c.moveToFirst())
{
    do {
        DisplayContact(c);
    } while (c.moveToNext());
}
db.close();

  SELECT - 选择语句 & WHERE - 筛选语句

public Cursor getContact(long rowId) throws SQLException 
{
    Cursor mCursor =
            db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
            KEY_NAME, KEY_EMAIL}, KEY_ROWID + "=" + rowId, null,  //此处为 where 语句的内容.
            null, null, null, null);
    if (mCursor != null) {
        mCursor.moveToFirst();
    }
    return mCursor;
}
//---get a contact---
db.open();
Cursor c = db.getContact(2);
if (c.moveToFirst())        
    DisplayContact(c);
else
    Toast.makeText(this, "No contact found", Toast.LENGTH_LONG).show();
db.close();    

  UPDATE - 更新语句

public boolean updateContact(long rowId, String name, String email) 
{
    ContentValues args = new ContentValues();
    args.put(KEY_NAME, name);
    args.put(KEY_EMAIL, email);
    return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
//---update contact---
db.open();
if (db.updateContact(1, "Wei-Meng Lee", "weimenglee@gmail.com"))
    Toast.makeText(this, "Update successful.", Toast.LENGTH_LONG).show();
else
    Toast.makeText(this, "Update failed.", Toast.LENGTH_LONG).show();
db.close();

  DELETE - 删除语句

public boolean deleteContact(long rowId) 
{
    return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;  //null 为删除全部.
}
//---delete a contact---
db.open();
if (db.deleteContact(1))
    Toast.makeText(this, "Delete successful.", Toast.LENGTH_LONG).show();
else
    Toast.makeText(this, "Delete failed.", Toast.LENGTH_LONG).show();
db.close();

  查询指定名称的个数.

public int queryStudentBySid(String sid)
{
    Cursor cursor = SQLiteDB.query(DATABASE_TABLE_NAME, null, KEY_SID + "=" + sid, null, null, null, null);
    return cursor.getCount();
}

  ORDER BY - 排序语句 (DESC & ASC)

public Cursor ascendStudents() 
{
    Cursor cursor = SQLiteDB.query(
            DATABASE_TABLE_NAME, new String[]{KEY_ID, KEY_SID, KEY_NAME, KEY_GENDER, KEY_HOMETOWN}, 
            null, null, null, null, KEY_SID);
    if (cursor != null) {
        cursor.moveToFirst();
    }
    return cursor;
}
public Cursor descendStudents() 
{
    Cursor cursor = SQLiteDB.query(
            DATABASE_TABLE_NAME, new String[]{KEY_ID, KEY_SID, KEY_NAME, KEY_GENDER, KEY_HOMETOWN}, 
            null, null, null, null, KEY_SID + " DESC");  //order by 语句内容.
    if (cursor != null) {
        cursor.moveToFirst();
    }
    return cursor;
}


V. Content Provider 使用简介:

参考:Beginning Android 4 Application Development - Page 293

1. Content Provider 主要是用来获取其他程序的信息,例如可以取得通讯录中的内容等。

※ 参考:总结Content Provider的使用

 

public class McProvider extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mc_provider);
        
        Uri allContactsUri = Uri.parse("conten://contacts/people");
        Cursor cursor;

        if (android.os.Build.VERSION.SDK_INT < 11) {
            cursor = managedQuery(allContactsUri, null, null, null, null);
        }
        else {
            CursorLoader cursorLoader = new CursorLoader(this, allContactsUri, null, null, null, null);
            cursor = cursorLoader.loadInBackground();
        }
        
        String[] columns = new String[] {
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts._ID};
        
        int[] views = new int[] {R.id.contactName,R.id.contactID};
        
        SimpleCursorAdapter adapter;
        
        if (android.os.Build.VERSION.SDK_INT < 11) {
            adapter = new SimpleCursorAdapter(this, R.layout.activity_mc_provider, cursor, columns, views);
        }
        else {
            adapter = new SimpleCursorAdapter(this, R.layout.activity_mc_provider, cursor, columns, views, 
                    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        }
        
        this.setListAdapter(adapter);
    }

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值