Android中的数据存储

分类

  • 共享参数存储
  • File存储(内部,外部)
  • SQLite数据库
  • Content Provider
  • 网络存储

共享参数存储 Shared Preferences

特点

  • 存放轻量级的数据
  • 本质上xml的格式存数据,通过键值对的方式对数据进行读写
  • 应用程序被卸载后,文件也会被删除

存储数据的类型

boolean# # int String long float

路径

data/data/包名/shared_preds/名字.xml

存储数据

 
SharedPreferences sPreferences=getSharedPreferences(name,mode)//得到SharedPreferences对象

Editor editor = sPrefences.edit();//得到共享参数的编辑对象

editor.putString(key,value);//向共享参数中存入数据

editor.commit();//别忘记提交

读取数据

SharedPreferences sPreference=getSharedPreferences(name,mode);//得到SharedPreferences对象

String msg=sPreference.getString(key,defValue);//根据key读取数据defValue为默认值

SharedPreferences源码

public interface SharedPreferences {

        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
    }

    public interface Editor {
      //存数据,需要定义Editer
        Editor putString(String key, @Nullable String value);

        Editor putStringSet(String key, @Nullable Set values);

        Editor putInt(String key, int value);

        Editor putLong(String key, long value);

        Editor putFloat(String key, float value);

        Editor putBoolean(String key, boolean value);

        Editor remove(String key); 

        Editor clear();  

        boolean commit();    

        void apply();
    }
  //取数据
    Map

File存储

内部存储 Internal Storage

特点
  • 文件只能被当前应用程序访问,其他应用程序不能访问
  • 文件卸载后,其中的数据也会随之清除
路径

data/data/包名/files/xxx.xxx(名字.类型)

存入数据
FileOutputStream fos=openFileOutput(fileName,mode);//打开文件输出流

fos.write(byte[]);//写入数据

fos.close();//关闭流
取出数据
FileInputStream fis=openFileInput(fileName);//打开文件输入流

byte[] buffer=new byte[fis.avaiable()];//读取数据
fis.read(buffer);
//这儿可以根据要读取的数据类型,定义相应的接收

fis.close()//关闭流

外部存储 External Storage

特点
  • sdcard分为两个部分,一个为公共目录,一个是私有目录
  • 公共目录下的文件可以被其他目录访问,私有目录的只能被本应用程序访问
  • 卸载应用程序后,sd公共目录中的文件不会比清除,私有目录中的文件会被清除
路径
  • 公有:storage/sdcard
  • 私有:storage/sdcard/Android/data/包名/files/
权限问题
  • WRITE_EXTERNAL_STORAGE 写sd卡权限
  • READ_EXTERNAL_STORAGE 读sd卡权限
  • 注意:有时用studio自带的模拟器,加了权限,在运行时,却不能存入,提示FileNotFound及权限问题,这是模拟器的问题,用手机或者换个模拟器就行了
sd卡的状态

sd卡的状态可以用Environment.getExternalStorageState()判断
MEDIA_MOUNTED为挂载状态,表示可以使用

获得目录路径
  • Environment.getExternalStoragePublicDirectory();//公共目录
  • Environment.getExternalStorageDirectory();//私有目录
Environment中对应源码
//其中一些对象Environment中内部类UserEnvironment定义的
public static String getExternalStorageState() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return getExternalStorageState(externalDir);
    }

public static File getExternalStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirs()[0];
    }

public static File getExternalStoragePublicDirectory(String type) {
        throwIfUserRequired();
        return sCurrentUser.buildExternalStoragePublicDirs(type)[0];
    }

数据库存储

一些数据库

Oracle SQLServier Mysql SQLite

SQLite

Android系统中集成的轻量级的数据库

特点
  • 轻量级:一个动态的数据库,以单个文件的方式进行存取
  • 零配置:无需安装
  • 跨平台:可以支持多个操作系统
  • 嵌入式:嵌入手机
存放的数据类型
  • NULL 空值
  • INTENGER 整型
  • VARCHAR 可变长度的字符数据
  • TEXT 文本字符串
  • BOOLEAN 布尔
sql语句
//创建
create table if not exists 表名(字段名 字段类型 primary key autoincrement,字段名 字段类型,...)

//插入
insert into 表名(字段)Values(值)

//修改
update 表名 set 字段名=值 where 条件

//查询
select(显示的字段) from 表名 where 条件

//删除
delete from 表名 where 条件
数据库核心类
SQLiteDatabase 管理和操作数据库
特点
  • 提供了一个管理数据库的类
  • 提供了增删改查数据库的方法
  • 数据库的名称在当前应用程序中是唯一的, 而不是在所有应用程序值唯一
SQLiteDatabase db=openOrCreateDatabase(name,mode,factory);
//name,数据库名称;
//mode,数据库访问权限;
//factory,游标工厂.

//执行数据库操作的方式:
//1、直接:
String sql="insert into person(name,age) values('张三',21)";
//sql为数据库语言
db.execSQL(sql);
//2、使用SQLiteDatabase里封装好的一些方法

//查
/**
 * distinct     去除重复
 * table        表名
 * columns      字段  new String[]{"_id","name","age"}   如果查询所有数据, 则null
 * selection        条件  where之后的内容
 * selectionArgs    占位符的取值
 * groupBy      分组
 * having       放在where之后再次筛选
 * orderBy      排序 
 * limit        区间
 */
db.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy,limit);

//删
/***
 * table        表名
 * whereClause  删除的条件 where之后的内容
 * whereArgs    占位符的取值
 */
db.delete(table, whereClause, whereArgs);

//改
/**
 * table    表名
 * values   ContentValues 
 * whereClause  条件 占位符 where 之后的内容
 * whereArgs    占位符对应的值  
 */
db.update(table, values, whereClause, whereArgs);

//增
/**
 * table            表名
 * nullColumnHack   null    insert into person (nullColumnHack) values(null)
 * values           ContentValues(key,value)
 */
db.insert(table, nullColumnHack, values);

//其中ContentValues(key,value)创建使用
//key  表中的字段名称, value  对应的数据内容
ContentValues values = new ContentValues();
values.put("name", "行文不及码如风");
values.put("age", 23);

Context类中部分代码:

    /**
     * Open a new private SQLiteDatabase associated with this Context's
     * application package.  Create the database file if it doesn't exist.
     */
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
            int mode, CursorFactory factory);
    /**
     * Open a new private SQLiteDatabase associated with this Context's
     * application package.  Creates the database file if it doesn't exist.
     */
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
            int mode, CursorFactory factory, DatabaseErrorHandler errorHandler);
    /**
     * Delete an existing private SQLiteDatabase associated with this Context's
     * application package.
     */
    public abstract boolean deleteDatabase(String name);
    /**
     * Returns the absolute path on the filesystem where a database created with
     */
    public abstract File getDatabasePath(String name);
    /**
     * Returns an array of strings naming the private databases associated with
     * this Context's application package.
     */
    public abstract String[] databaseList();

SQLiteDatabase中部分源码:

   
    public void execSQL(String sql) throws SQLException {
        executeSql(sql, null);
    }
    public Cursor query(String table, String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having,
            String orderBy) {

        return query(false, table, columns, selection, selectionArgs, groupBy,
                having, orderBy, null /* limit */);
    }
    public long insert(String table, String nullColumnHack, ContentValues values) {
        try {
            return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
        } catch (SQLException e) {
            Log.e(TAG, "Error inserting " + values, e);
            return -1;
        }
    }
    public int delete(String table, String whereClause, String[] whereArgs) {
        SQLiteStatement statement =  new SQLiteStatement(this, "DELETE FROM " + table +
                (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
        try {
            return statement.executeUpdateDelete();
        } catch (SQLiteDatabaseCorruptException e) {
            onCorruption();
            throw e;
        } finally {
            statement.close();
        }
    }
    public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
        return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE);
    }

SQLiteOpenHelper 用于数据库的创建和版本更新
作用
  • 初始化数据库
  • 升级数据库 (更新)
  • 打开数据库连接 (存在则打开,不存在则创建并打开连接)
使用
//定义一个类继承SQLiteDatabase

public class MySqliteHepler extends SQLiteOpenHelper{
    //提供一个构造方法
    public MySqliteHepler(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        //第一次创建数据库时执行, 只会执行一次
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        //当数据库的版本号发生变化后, 执行此方法, 会执行多次
    }

}
MySqliteHepler helper=new MySqliteHepler(context);
SQLiteDatabase db = helper.getWritableDatabase();
SQLiteDatabase db = helper.getReadableDatabase();
...

Cursor

默认游标的位置位于所有数据之上

boolean cursor.move(offset) 游标向上或者向下移动指定的条数,并且判断是否存在

boolean cursor.moveToNext() 游标移动到下一条数据, 并且判断下一条数据是否存在

boolean cursor.moveToPrevious() 游标移动到上一条数据, 并且判断上一条数据是否存在

boolean cursor.moveToFirst() 游标移动到第一条数据, 并且判断第一条数据是否存在

boolean cursor.moveToLast() 游标移动到最一条数据, 并且判断最一条数据是否存在

boolean cursor.moveToPosition() 游标移动到指定数据, 并且判断该数据是否存在

int cursor.getCount() 得到游标中所以数据的数量

取值:

获取内容: cursor.getString(列的编号) // 列的编号从0开始

根据列的名称得到列的编号: cursor.getColumnIndex(字段名称)

SimpleCursorAdapter
特点
  • 数据源中必须要包括一个”_id” 的字段
  • 刷新适配器, 没有效果
/** 
* context       上下文对象
* layout        每个Item显示的布局页面
* c         游标(数据源) 
* from          String[] cursor中所有字段名称的数组 
* to            int[]    布局页面中Id的数组
* flags         标记, 自动更新(观察者)
*/
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
        context,
        layout, 
        c, 
        from,
        to,
        flags);
//例如:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
        this,
        R.layout.item, //子布局
        cursor, 
        new String[]{"name","age"},//两个属性名
        new int[]{R.id.name,R.id.age},//两个属性对应的子布局中控件id
        SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

Content Provider

是什么

特点
  • 所有应用程序之间数据存储和检索的桥梁
  • 应用程序之间数据共享的唯一途径
注意
  • 如果想访问内容提供者提供的数据,那么需要通过ContentResolver对象获取数据内容
  • 想要共享自己的数据,那么需要自定义一个内容提供者,把自己的数据共享出去

做什么

  • 实现多个应用程序之间的共享

URI

  • content://应用程序包名.provider/表名 —自定义

分析

  • ContentResolver 内容更解析器:负责解析ContentProvider暴露出来的数据
  • ContentProvider 内容提供者:负责暴露数据

实例

访问手机中提供的数据

访问短信记录

    private ListView listView;
    private Cursor cursor;
    private SimpleCursorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView=(ListView) findViewById(R.id.list_view);
        //得到数据源
        //得到内容解析器对象
        ContentResolver contentResolver=getContentResolver();
        //解析数据
       /**
         * uri              访问ContentProvider提供的路径
         * projection       查询数据库中的字段
         * _id, address     地址, data 日期, body 内容, type 短信类型
         * type         (1接收,2发送,3草稿箱,4未读的短信,5发送失败的短信 )
         * selection        查询的条件
         * selectionArgs    占位符的取值 
         * sortOrder        排序
         */
        Uri uri=Uri.parse("content://sms");
        String [] projection=new String[]{"_id","address","date","body","type"};
        cursor=contentResolver.query(uri, projection, null, null, null);
        adapter=new SimpleCursorAdapter(
        getApplicationContext(),
        R.layout.item,
        cursor,
        new String[]{"address","body"},
        new int[]{R.id.content_address,R.id.content_body},
        SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        listView.setAdapter(adapter);
    }

自定义ContentProvider

  • 定义一个类, 继承ContentProvider, 重写父类的6个方法
    onCreate()初始化工作

    query(Uri uri,....)  查询数据

    insert(Uri uri,....)  插入数据

    update(Uri uri,...)   修改数据

    delete(Uri uri,..)    删除数据

    getType()        只实现, 不处理
  • 声明ContentProvider的唯一标识 (内容只能为小写的字母,建议使用: 包名+数据库的名称)
  • 声明访问数据库的Code码 (在ContentProvider 暴露数据时使用)
  • 声明Uri的匹配器,并且实例化, 注册Uri
    private static  UriMatcher uriMatcher;

    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCHER);
        uriMatcher.addUri(唯一标识, 路径

网络存储

Android提供了通过网络来实现数据的存储和获取的方法。

我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。

具体需要熟悉Java.NET.* ,Android.Net.* 这两个包的内容,详细的类与方法的说明,请参考SDK

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android,有多种方式可以存储数据,以下是其一些常见的数据存储方式: 1. Shared Preferences(共享首选项): - Shared Preferences是Android提供的一种轻量级的存储方式,用于存储少量的键值对数据。它适用于存储一些简单的配置信息或用户偏好设置。Shared Preferences使用键值对的方式存储数据,并且只能存储基本数据类型。 2. 内部存储: - 内部存储是应用程序私有的文件存储空间,可以用来存储应用程序的私有数据。可以使用File类来进行读写操作。内部存储适用于存储较小的数据文件。 3. 外部存储: - 外部存储是指SD卡或其他外部存储设备上的存储空间。Android提供了一些API(如Environment.getExternalStorageDirectory())来访问外部存储。外部存储适用于存储大量的文件或多媒体资源。 4. SQLite数据库: - SQLiteAndroid内置的关系型数据库,可以用于存储结构化的数据。开发者可以使用SQLiteOpenHelper类来创建和管理数据库,以及执行常见的CRUD(创建、读取、更新、删除)操作。 5. ContentProvider(内容提供器): - ContentProvider是用于在应用程序之间共享数据的组件。它提供了标准的接口和方法,允许应用程序对数据进行查询、插入、更新和删除操作。ContentProvider常用于共享数据库或文件等数据。 6. 网络存储: - Android应用程序可以通过网络与服务器进行数据交互,将数据存储在远程服务器上。常用的网络存储方式包括使用HTTP协议与服务器进行通信、使用RESTful API进行数据交互等。 综上所述,Android有多种数据存储方式可供选择,开发者可以根据具体的需求和场景选择合适的方式来存储和管理数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值