从零学Android(十三)、Android中的数据存储方式简介

来源:互联网 发布:餐饮进销存软件免费版 编辑:程序博客网 时间:2024/05/22 17:03

Android提供了以下5种存储数据的方式:

【1】Shared Preferences:以key-value的形式保存一些基本数据类型的数据。

【2】Internal Storage:内部存储一些应用私有数据到设备内存中。

3】External Storage:存储一些公开数据到外部存储设备中,如SD卡等。

【4】SQLite Databases:存储一些结构化的数据到自己的私有数据库中。

【5】Network Connection:将数据保存到自己的服务器上。

另外,Android还提供了content provider来让你将自己应用的私有数据暴露给其它的应用。

一、Shared Preferences

SharedPreferences类提供了一些API方法帮忙我们存储基本数据类型数据,如booleans, floats, ints, longs, and strings。使用Shared Preferences方法存储数据,主要有四个步骤:

【1】通过调用getSharedPreferences()方法或getPreferences()方法获取SharedPreferences对象

【2】SharedPreferences对象的edit()方法获取SharedPreferences.Editor对象

【3】调用SharedPreferences.Editor对象的如putBoolean()等方法,存储数据。

【4】调用SharedPreferences.Editor对象的commit()方法提交数据。

其中关于获取SharedPreferences对象的两个方法间的区别如下:

getSharedPreferences():如果你需要使用到多个SharedPreferences文件,那么你可以通过该方法去获取SharedPreferences对象,这些对象通过name来加以标识。

getPreferences():如果你只需要对单个Activity使用SharedPreferences文件,那么你可以使用该方法去获取SharedPreferences对象,它返回的是一个以(当前Activity的完整类名 - 项目包路径)后的字符串作为name的SharedPreferences对象。

最后你可以通过使用SharedPreferences对象的如getBoolean()等方法获取到之前保存的数据。使用例子:

public class Calc extends Activity {    public static final String PREFS_NAME = "MyPrefsFile";    @Override    protected void onCreate(Bundle state){       super.onCreate(state);       . . .       // Restore preferences       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);       boolean silent = settings.getBoolean("silentMode", false);       setSilent(silent);    }    @Override    protected void onStop(){       super.onStop();      // We need an Editor object to make preference changes.      // All objects are from android.context.Context      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);      SharedPreferences.Editor editor = settings.edit();      editor.putBoolean("silentMode", mSilentMode);      // Commit the edits!      editor.commit();    }}

二、Internal Storage

内部存储的数据对于其它应用和用户而言,是不可见的,它保存在当前应用的私有文件夹下。当用户卸载APP时,这些数据也会被删除。

2.1 创建并写入数据到内部存储

1.你可以通过openFileOutput()方法传入一个fileName和fileMode打开一个文件的输出流,这个方法返回一个FileOutputStream对象。

2.然后调用FileOutputStream对象的write()方法写入数据。

3.写完数据后记得调用close()方法关闭流。

比如:

String FILENAME = "hello_file";String string = "hello world!";FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);fos.write(string.getBytes());fos.close();

MODE_PRIVATE会给你创建一个专属于你APP的文件(或者替代当前存在的同名的文件),其它还有诸如MODE_APPEND(在当前文件的内容后面增加内容),MODE_WORLD_READABLE(其它应用可用读取该文件)和MODE_WORLD_WRITEABLE(其它应用可以写数据到这个文件)三种可用的文件权限。

2.2 内部存储设备中读取文件

1.调用openFileInput()方法,并且传入一个文件名fileName,这个方法会返回一个FileInputStream对象。

2.使用FileInputStream对象的read()方法读取数据。

3.在读取完数据后,记得调用close()方法关闭流。

PS:如果你希望保存一些静态文件到APP中,那么可以将它们放置到res/raw/目录下,然后通过openRawResource()方法并传递一个R.raw.<filename>形式的资源ID去获取这个静态文件,这个方法会返回一个InputStream对象,以便你能读取其中的数据,不过这种方式不允许你往文件中写入数据。

上面的openFileInput()方法或openFileOutput()方法打开的是/data/data/appPackageName/files路径下的文件。

2.3 保存缓存文件

如果你希望保存一些不用持久保存的临时文件,你可以使用getCacheDir()方法打开/data/data/appPackageName/cache的File对象。当系统内存不足时,这个路径下的文件会首先被删除,你不应该依赖系统去帮你清除这些文件,你可以自己给这个文件设置一个合理的大小空间,比如1M。当用户卸载APP时,这个文件会被移除。

getFilesDir():返回/data/data/appPackageName/files路径下的文件

getDir():创建或打开一个存在的/data/data/appPackageName/files路径下的文件

deleteFile():删除/data/data/appPackageName/files路径下的文件

fileList():返回/data/data/appPackageName/files路径下的文件列表

三、External Storage

外部存储器(如SD卡)中的文件对于所有的应用都是可读的,而且用户还能删除这个文件,所以存储在外部存储器上的文件是没有安全保障的。

3.1 获取外部存储器权限

如果你希望对外部存储设备进行读写操作,你需要向系统申请对应的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。如:

<manifest ...>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    ...</manifest>
如果你需要读和写的权限,你仅仅需要申请WRITE_EXTERNAL_STORAGE权限,因为它会隐式地调用读权限。

PS:从Android 4.4(API level 18)开始,当读取当前APP在外部存储设备上的私有文件时,可以不申请权限。


3.2 检查设备是否可用

在你对外部存储设备进行读写操作之前,你需要先调用getExternalStorageState()方法来检查外部存储设备的状态,外部设备可能正挂载在电脑上或找不到,只可读等其他状态。比如说,你可以使用下面两个方法去检查存储设备的状态:

/* Checks if external storage is available for read and write */public boolean isExternalStorageWritable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state)) {        return true;    }    return false;}/* Checks if external storage is available to at least read */public boolean isExternalStorageReadable() {    String state = Environment.getExternalStorageState();    if (Environment.MEDIA_MOUNTED.equals(state) ||        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {        return true;    }    return false;}

3.3 保存和其它APP共享的数据文件

有时候,我们创建的文件可能需要提供给其它的APP也能使用,这个时候我们应该将这个文件放置到一个公共的路径下面。为了实现这个功能,我们可以使用getExternalStoragePublicDirectory()方法,并且传递如DIRECTORY_MUSIC,DIRECTORY_PICTURES,DIRECTORY_RINGTONES等,这样其它APP在浏览这些文件路径的时候,就能轻易地获取到你创建的文件。比如使用下面的方法去获取你创建的图片文件夹:

public File getAlbumStorageDir(String albumName) {    // Get the directory for the user's public pictures directory.    File file = new File(Environment.getExternalStoragePublicDirectory(            Environment.DIRECTORY_PICTURES), albumName);    if (!file.mkdirs()) {        Log.e(LOG_TAG, "Directory not created");    }    return file;}

3.4 保存当前APP私有的数据文件

如果你希望在外部存储设备上将文件保存为当前APP的私有文件,你可以使用getExternalFilesDir()方法获取到SD卡上APP私有文件路径,如:/storage/emulated/0/Android/data/appPackageName/files。这个方法同样接收一个type类型,如DIRECTORY_MUSIC,DIRECTORY_PICTURES,DIRECTORY_RINGTONES等。如果你不需要这些文件类型,你也可以传递一个null来获取到App私有文件夹的根路径。

从Android4.4(API level = 18)开始,读写外部存储器的私有路径文件不再需要READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限,所以在声明这个读写外部设备的权限时,你可以加上maxSdkVersion属性。如下:

<manifest ...>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"                     android:maxSdkVersion="18" />    ...</manifest>
注意:当用户卸载我们的APP时,外部存储设备的APP私有文件也会被删除,同时,系统的媒体浏览器也不会去浏览我们APP私有文件夹。所以一些属于用户的文件需要保存到公共的文件夹下,比如通过你的APP拍摄的照片等。

有时候,一个将一部分内部存储划分为外部存储的设备有可能提供一个SD卡的插槽,这个时候,当你的APP运行在4.3或者4.3以下版本的时候,getExternalFilesDir()方法返回的File是内部存储作为外部存储的那个路径,你的APP不能对SD卡进行读写操作,从Android4.4起,你可以使用getExternalFilesDirs()来获取这两个存储区,它返回的是一个File数组。这个数组中的第一个值就是内部私有文件区,一般情况下,你需要将文件读写到这个目录下,除非它不可用或者存储空间满了。如果你希望在4.3及其以下版本使用这个两个路径,你需要使用支持包中的方法:ContextCompat.getExternalFilesDirs()。它同样返回一个File数组,不过在4.3及以下时,一般只有一个值。

注意:虽然getExternalFilesDir()和getExternalFilesDirs()获取的文件区对于系统的媒体MediaStore Content Provider不可见,但是其它APP只要声明了READ_EXTERNAL_STORAGE权限,它就能查看到外部存储设备中的所有内容,包括这个文件区的内容;所以,如果你希望完全限制其它APP对文件的访问,你需要将文件保存在内部存储设备中,即data/data/appPackageName/files中。

3.5 保存缓存文件

如果你希望保存缓存文件到外部设备上,你可以使用getExternalCacheDir()方法,这个方法返回的File对象,在APP卸载时,也会自动被删除。和ContextCompat.getExternalFilesDirs()相似,你也可以通过调用ContextCompat.getExternalCacheDirs()来获取两个外部设备的缓存区。

为了保留缓存区域的大小以及APP的性能,在缓存文件不需要用时,记得将其删除。

四、SQLite Databases

Android完全支持SQLite数据库,你可以在你应用的任何地方通过数据库名称获取到这个数据库对象,而在其它的APP中则不能访问。

切记在Android中创建数据库的方法其实就创建一个SQLiteOpenHelper的子类,并且重写其onCreate()方法,在这个方法中,你可以通过执行SQL语句来创建数据库红的表。如下:

public class DictionaryOpenHelper extends SQLiteOpenHelper {    private static final int DATABASE_VERSION = 2;    private static final String DICTIONARY_TABLE_NAME = "dictionary";    private static final String DICTIONARY_TABLE_CREATE =                "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +                KEY_WORD + " TEXT, " +                KEY_DEFINITION + " TEXT);";    DictionaryOpenHelper(Context context) {        super(context, DATABASE_NAME, null, DATABASE_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(DICTIONARY_TABLE_CREATE);    }}
然后你可以通过使用其构造函数获取到一个SQLiteOpenHelper实现类的对象,而后使用getWritableDatabase()方法和getReadableDatabase()方法分别获取一个可写和可读的数据库SQLiteDatabase对象,SQLiteDatabase类提供了一系列的操作数据库的方法。

五、Network Connection

使用

  • java.net.*
  • android.net.*

两个包中的相关类,将数据保存在web服务器上。





0 0
原创粉丝点击