您的位置:首页 > 移动开发 > Android开发

Android几种数据存储的方式

2016-06-26 20:02 483 查看
这是我的第一篇博客,前言也不多说什么,有点小激动,还是直接进入正题吧。
RT,今天要写的是安卓几种数据存储的方式。
一,首先我想到的就是创建本地数据库,前段时间刚用了一个叫GreenDao的第三方,他的用法很简单,这里我直接贴上操作步骤和代码,网上很多教程(我也是跟着教程来,然后再自己加以琢磨)。

(下面这个是基本配置网上抄的)

一. 在 ANDROID 工程中配置「GREENDAO GENERATOR」模块

在 .src/main 目录下新建一个与 java 同层级的「java-gen」目录,用于存放由 greenDAO 生成的 Bean、DAO、DaoMaster、DaoSession 等类。 

配置 Android 工程(app)的 build.gradle,如图分别添加 sourceSets 与dependencies。 

1

2

3

4

5
sourceSets {

        
main {

            
java.srcDirs = [
'src/main/java'
'src/main/java-gen'
]

        
}

    
}


1
compile 
'de.greenrobot:greendao:2.1.0'(这里注意下版本要高) 



二. 新建「GREENDAO GENERATOR」模块 (纯 JAVA 工程)

通过 File -> New -> New Module -> Java Library -> 填写相应的包名与类名 -> Finish.

在另外的模块里面的gradle配置 daoexamplegenerator 工程的 build.gradle,添加 dependencies.

 

1
compile 
'de.greenrobot:greendao-generator:1.3.1'


编写 ExampleDaoGenerator 类,注意: 我们的 Java 工程只有一个类,它的内容决定了「GreenDao Generator」的输出,你可以在这个类中通过对象、关系等创建数据库结构,下面我将以注释的形式详细讲解代码内容。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40
public class ExampleDaoGenerator {

    
public static void main(String[] args) throws Exception {

        
// 正如你所见的,你创建了一个用于添加实体(Entity)的模式(Schema)对象。

        
// 两个参数分别代表:数据库版本号与自动生成代码的包路径。

        
Schema schema = 
new
 
Schema(1, 
"me.itangqi.greendao"
);//版本号,生成代码的包路径

//      当然,如果你愿意,你也可以分别指定生成的 Bean 与 DAO 类所在的目录,只要如下所示:

//      Schema schema = new Schema(1, "me.itangqi.bean");

//      schema.setDefaultJavaPackageDao("me.itangqi.dao");

 
        
// 模式(Schema)同时也拥有两个默认的 flags,分别用来标示 entity 是否是 activie 以及是否使用 keep sections。

        
// schema2.enableActiveEntitiesByDefault();

        
// schema2.enableKeepSectionsByDefault();

 
        
// 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。

        
addNote(schema);

 
        
// 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。

        
// 其实,输出目录的路径可以在 build.gradle 中设置,有兴趣的朋友可以自行搜索,这里就不再详解。

        
new
 
DaoGenerator().generateAll(schema, 
"/Users/tangqi/android-dev/AndroidStudioProjects/MyGreenDAO/app/src/main/java-gen"
);//这句必须要

    
}

 
    
/**

     
* @param schema

     
*/

    
private static void addNote(Schema schema) {

        
// 一个实体(类)就关联到数据库中的一张表,此处表名为「Note」(既类名)

        
Entity note = schema.addEntity(
"Note"
);//创建关联实体类的表,输入类的名字

        
// 你也可以重新给表命名

        
// note.setTableName("NODE");

 
        
// greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值

        
// 接下来你便可以设置表中的字段:

        
note.addIdProperty();//开始设置字段了

        
note.addStringProperty(
"text"
).notNull();

        
// 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。

        
// For example, a property called “creationDate” will become a database column “CREATION_DATE”.

        
note.addStringProperty(
"comment"
);

        
note.addDateProperty(
"date"
);

    
}

}


三. 生成 DAO 文件(数据库)

执行 generator 工程,如一切正常,你将会在控制台看到如下日志,并且在主工程「java-gen」下会发现生成了DaoMaster、DaoSession、NoteDao、Note共4个类文件。 

然后在studio右键点击 run```的 他就会出来一串write之类的东西主要看看是否有结果生成  不为0就好如我的   Processed 3 entities in 1010ms

如果在此处出错,你可以依据错误日志进行排查,主要看是否输出目录存在?其他配置是否正确?等

四. 在 ANDROID 工程中进行数据库操作

接下来的操作是在db(我喜欢这么命名)文件下新建一个openhelper类,里面有实力化的方法和一些增删改查的方法

举个例子(下面的内容和上面ExampleDaoGenerator类无关·····)

//实例化

public Anamial(Context context) {
alarmBeanList=new ArrayList<>();
try{
alarmBean= GetDaoSession.getDaoSession(context,"alarm.db").getAlarmBeanDao();
}catch (Exception e){
e.printStackTrace();
}
}
public static  AlarmDaoHelper getInstance(Context context){
if (alarmDaoHelper==null){
synchronized (AlarmDaoHelper.class){
if (alarmDaoHelper==null){
alarmDaoHelper=new AlarmDaoHelper(context);
}
}
}return alarmDaoHelper;
}

/*********增加数据*********/
@Override
public <T> void addDada(T data) {
if (alarmBean!=null&&data!=null){
alarmBean.insertOrReplace((AlarmBean) data);

}
}
/****删除数据****/

@Override
public void deleteData(Long id) {//这个id是要在你的生成的那个类里面的
if (alarmBean!=null&&id!=null){
alarmBean.deleteByKey(id);

}
//查询
/**
* get alarms by startdate
*
* @param startDate
* @return
*/
public List<AlarmBean> getAlarmsByStartDate(String startDate) {
if (startDate != null) {
Query query = alarmBean.queryBuilder()
.where(AlarmBeanDao.Properties.StartDate.eq(startDate))
.orderAsc(AlarmBeanDao.Properties.RelshowTime)//插入的意思
.build();

List<AlarmBean> notes = query.list();
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
return notes;
}
return emptyList;
}
//更新数据的话建议根据条件查询到数据之后,获得他对应的ID 在通过ID把原来的删除掉,再添加一条数据,这样就更新好了。

二,要讲的是偏好设置sharedPreferences

可以用来保存用户的一些简单的使用习惯信息,偏好设置实质上是/data/data/包/share_prefs/路径下的一个xml文件,文件名就是偏好设置的名字。
如何使用ShardPreference将数据持久化:
通过getSharedPreferences(String name,int mode)来获取一个SharedPreferences对象,一个应用可以有多个偏好设置文件,第一个参数决定用哪个,第二个参数表示模式,一般用MODE_PRIVATE,只能本应用来读(全局可读、全局可写这些模式不建议使用)
保存: 调用SharedPreferences对象的edit()方法,开始修改它,这个方法会返回一个Editor对象,我们调用这个对象的putXXX方法往里面放简单的信息,在写好后再调用commit()方法来确认
Activity中存入数据
//获取一个私有的偏好设置,名字为demo
SharedPreferences pref = getSharedPreferences("demo", MODE_PRIVATE);
//获取一个编辑器,开始对这个偏好设置进行读写操作
Editor editor = pref.edit();
//往编辑器里存放键值对信息
editor.putString("info", "w");
editor.putInt("num", 1000);
//确认,使上述信息生效
editor.commit();//东西一多的话用apply提交(另外开一个线程提交,异步操作,而commit有结果,apply没有结果)

Activity中获取数据
获取: 调用SharedPreferences对象的getXXX方法根据键获取值
SharedPreferences pref = getSharedPreferences("demo", MODE_PRIVATE);
//直接通过偏好设置对象获取存在其中的信息,通过键获取值
//第一个参数就是键名,第一个是默认值(没有存的情况下起作用)
String info = pref.getString("info", "信息还未存入");
int number = pref.getInt("num", 0);//是什么数据类型就get什么类型

三.存到应用程序的Data File目录

在内置存储器中,在应用程序目录中,可以保存稍微大些的文件信息,在应用程序被删除时,这个目录及内部的所有内容也会连带删除(在/data/data/包名/files目录下)
写文件示例:

public void save()

 {

 

        try {

            FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);//openFileOutput(): 获取一个字节输出流,向内置文件写

            outStream.write(text.getText().toString().getBytes());

            outStream.close();//关闭流

        } catch (FileNotFoundException e) {

            return;

        }

        catch (IOException e){

            return ;

        }

 

 } 

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。

创建的文件保存在/data/data//files目录,如: /data/data/cn.itcast.action/files/itcast.txt ,

读取文件示例:

public void load()

{

    try {

        FileInputStream inStream=this.openFileInput("a.txt");//openFileInput(): 方法获取一个字节输入流,用来读

        ByteArrayOutputStream stream=new ByteArrayOutputStream();

        byte[] buffer=new byte[1024];

        int length=-1;

while((length=inStream.read(buffer))!=-1)   {

            stream.write(buffer,0,length);

        }

 

        stream.close();

        inStream.close();

        text.setText(stream.toString());

    } catch (FileNotFoundException e) {

        e.printStackTrace();

    }

    catch (IOException e){

        return ;

    }

 

}  

对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。(权限记得加上不然很蛋疼)

四.存到应用程序的Data cache目录缓存

在内置存储器中,在应用程序目录中,也可以保存大文件,和File目录的区别是,在存储空间吃紧的情况下,这个目录下的内容可能被自动删除(在/data/data/包名/cache目录下)
File.getCacheDir():获取代表缓存路径的文件对象,然后可以在这个路径下new文件对象,再使用输入流、输出流对文件进行处理
Activity还提供了getCacheDir()和getFilesDir()方法:
getCacheDir()方法用于获取/data/data//cache目录 getFilesDir()方法用于获取/data/data//files目录。

五.sdcard 外存

Sd卡,外置存储器中可以保存更大一些的文件,在应用程序删除时数据可以保留下来
首先,要访问外部存储设备,必须要声明write_external_storage 权限。
在代码中,要对外存操作,先要判断sd卡是否已挂载。用Environment的静态方法getExternalStorageState()方法获取外存的状态,如果是mounted的话说明已经挂载,如果是removed则没有挂载
3、使用EnvirogetExternalStorageDirectory方法获取sd卡根路径的File对象,再用getPath获取其路径字符串。sd卡根目录是/storage/sdcard
在getExternalStoragePublicDirectory方法中传入DIRECTORY_PICTURES,就返回这个android系统在外存中存储图片的公共目录,在这里是/storage/sdcard/Pictures
在getExternalStoragePublicDirectory方法中传入DIRECTORY_DOWNLOADS,,就返回这个系统在外存中存放下载的文件的公共目录,在这里是/storage/sdcard/Downloads
......
注意:有些手机的文件路径是定制的,所以尽量要使用api去获取路径,而不要将路径写死,避免硬件厂商定制路径造成的bug
除了sd卡中的公有目录,还可以在我们程序自己定的私有目录下读写文件。在sd卡根目录上创建我们自己的目录file.mkdirs(),并在其中创建文件进行读写
 
另外:为了避免sd卡空间不足造成损失,我们可以预先判断sd卡空间,使用StatFs类,先创建一个statFs对象,再用其中的一些方法进行判断。
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
int availableBlocks = stat.getAvailableBlocks();//获取sd卡中可用的块数
int blockCount = stat.getBlockCount();//获取sd卡中块的总数
int blockSize = stat.getBlockSize();//获取每个块的字节数
可用块数*每块字节数=可用字节数;总块数*每块字节数=总字节数
注意:不要用getFreeBlocks(),这个是空闲块数,空闲不一定可用

六.将数据保存在服务器端

通过post传参方式,将文件上传到服务器端(云端)
try {
    HttpURLConnection con = (HttpURLConnection) new URL("http://10.31.151.216:8080/up/upload").openConnection();
    con.setDoOutput(true);
    con.setRequestMethod("POST");
    con.setRequestProperty("Content-Type", "multipart/form-data;"+ " boundary=1234");
    con.connect();
    OutputStream os = con.getOutputStream();
    os.write("1234\r\n".getBytes());
    os.write("Content-Disposition: form-data; name=\"file1\"; filename=\"android.png\"\r\n".getBytes());
    os.write("\r\n".getBytes());
    FileInputStream fis = new FileInputStream("e:/android.png");
    int n= 0;
    byte[] buffer = new byte[1024];
    while((n = fis.read(buffer)) != -1){
        os.write(buffer, 0, n);
    }
    fis.close();
    os.write("\r\n\r\n".getBytes());
    os.write("123455\r\n".getBytes());
    System.out.println("read");
    BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String line =  null;
    while((line = br.readLine())!=null){
        System.out.println(line);
    }
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

好了,以上是我总结的几种数据存储的方式,后面几种写得比较简单,以后慢慢补齐吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: