- 数据存储的5种方式
使用API Guide学习数据存储的五大存储方式。--面试的时候会问的
- Shared Preferences(共享参数) : 使用键值对的形式去存储私有数据,这种数据只有当前应用可以访问,其他应用无法访问。(数据是以xml的形式存放在data/data/应用程序包名/….)
- Internal Storage (内部存储):其实是以文件的方式,把数据存储到内部存储器上。
- External Storage (外部存储): 其实是以文件的方式把数据存储在外部存储器上。
- SQLite Databases(数据库) : 把数据存储在私有的数据库文件内
-
Network Connection(网络存储) :把数据存储到远端网络上的服务器上。
- SharedPreferences存储
SharedPreferences是Android系统提供的一个通用的数据持久化框架,用于存储和读取key-value类型的原始基本数据类型对,目前支持String、int、long、float、boolean等基本类型的存储
SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名,上次最后设置的配置信息(如:是否打开音效、是否使用振动,小游戏的玩家积分等)。当再次启动程序后依然保持原有设置(即使你的应用程序已经退出)。SharedPreferences用键值对方式存储,方便写入和读取。
(你可以把它理解成一个只能存储基本数据类型和String类型和Set<String>类型的MAP集合)
常用方法:
写数据步骤:
- 根据Context获取SharedPreferences对象
haredPreferences本身是一个接口,无法直接创建实例,通过Context.getSharedPreferences(String name, int mode)方法来获取实例.
SharedPreferences sp = ctx.getSharedPreferences("user", MODE_PRIVATE);
说明:参数一:文件名(不需要扩展名,会自动使用xml作为扩展名) 参数二:文件的访问模式。共四种:
Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768(SharedPreferences不支持)
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
(最后两种模式,从4.2开始android已经不推荐使用了!!!)
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
MODE_MULTI_PROCESS :这个是一个标示位,2.3和2.3以前默认都是开启的,2.3以后是默认不开启。主要用于跨进程访问。
2、利用edit()方法获取Editor对象。
SharedPreferences.Editor editor = settings.edit();
获得一个编辑器,使用这个编辑可以向文件中写入数据
3、通过Editor对象存储key-value键值对数据。
editor.putString(“name”,”lisi”);
editor.putString(“sex”,”男”);
存入数据,可以写字符串、int、long、float、boolean和Set<String>
4、调用Editor对象的commit()方法提交数据。
必须调用该方法,否则上述数据不会存入到文件中。
读数据步骤:
- 根据Context获取SharedPreferences对象
调用SharedPreferences的getXxx(key, defaultValue)方法,取得相应 key对应的值
- 内部存储
内部存储路径是: /data/data/app包名/files
注意:真机若想看到此目录,必须root之后,安装相应的文件浏览器才可以看到,模拟器无此限制。
特点:用户看不到,应用中的数据大多数不允许被其他应用访问
通过I/O流进行读写操作
在Activity内部调用:
- openFileInput(不需要路径的文件名) //打开一个输入流,可以从指定的文件中读取数据
2.openFileOutput(不需要路径的文件名, mode) //打开一个输出流,可以向输入流写数据,然后数据保存到指定的文件中。
- 外部存储
- 给app申请需要的权限。(尽量多申请)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
允许向sd写数据的权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
允许挂载和卸载sd
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
允许读sd数据的权限。(这个权限默认是开启的,但是建议仍然申请,以备后患)
2.调用Enviroment的getExternalStorageState()方法来判断手机是否插入SD卡。
String state = Environment.getExternalStorageState();
// 如果sd卡存在,并且正常挂载,可读写
if(state.equals(Environment.MEDIA_MOUNTED)){
}
Environment.MEDIA_MOUNTED 已经挂载
Environment.MEDIA_MOUNTED_READ_ONLY 已经挂载,但是只读状态
Environment.MEDIA_CHECKING 正在检查SD卡
Environment.MEDIA_UNKNOWN 介质未知
Environment.MEDIA_UNMOUNTED 移除了
3.调用Environment的Environment.getExternalStorageDirectory();获得外部存储器的sd卡的目录。
返回值类型是File类型。
4.创建相应的的IO流进行数据的读写。
补充:
1.获得外部存储的公共目录:Envirment.getExternalStoragePublicDirectory(参数) 参数:(Environment.DIRECTORY_MOVIES 电影
Environment.DIRECTORY_MUSIC 音乐
Environment.DIRECTORY_DOCUMENTS 文件
Environment.DIRECTORY_DOWNLOADS 下载
Environment.DIRECTORY_PICTURES 图片
Environment.DIRECTORY_RINGTONES 铃声)
2.获得外部该app的私有存储目录:context.getExternalFilesDir(type) ; type可以指定类型,然后会在相应的类型。如果不指定相应的类型,则获得路径是:Android/data /包名/files
DIRECTORY_ALARMS //警报的铃声
DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
DIRECTORY_DOWNLOADS //下载文件保存的位置
DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载的电影
DIRECTORY_MUSIC //音乐保存的位置
DIRECTORY_NOTIFICATIONS //通知音保存的位置
DIRECTORY_PICTURES //下载的图片保存的位置
DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
DIRECTORY_RINGTONES //保存铃声的位置
3.获取磁盘空间大小:
File root = Environment.getExternalStorageDirectory(); //获得外部存储目录
StatFs Fs = new StatFs(root.getAbsolutePath()); //该对象可以 获取指定目录的文件系统的信息
le total = statFs.getTotalBytes() / 1024.0 / 1024.0; //获取总的大小
这个方法API18才能用
le current = statFs.getAvailableBytes() / 1024.0/ 1024.0; //获取可用大小
Toast.makeText(this, "" + total + " " + current, 1).show();
注意:获取路径的时候,公共的一般是用的Environment的方法,app私有的一般是使用的上下文对象的方法。
android中常用路径总结:
1、公共路径:所有的路径都可以访问
System.out.println(Environment.getDataDirectory()); // /data
System.out.println(Environment.getDownloadCacheDirectory()); // /cache
System.out.println(Environment.getExternalStorageDirectory()); // /storage/sdcard
System.out.println(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS)); // /strorage/sdcard/Alarms
System.out.println(Environment.getRootDirectory()); // /system
2、私有路径:只有当前应用可以访问
System.out.println(getFilesDir()); // /data/data/包名/files
System.out.println(getCacheDir()); // /data/data/包名/cache
System.out.println(getExternalCacheDir()); // /storage/sdcard/Android/data/包名/cache
// /storage/sdcard/Android/data/包名/files/DCIM
System.out.println(getExternalFilesDir(Environment.DIRECTORY_DCIM));
- 网络存储
分别利用HttpURLConnection和HttpClient来完成文件上传到远端服务器,把文件存储到远端服务器上面。
件上传服务器端:
需要的jar包:
request.setCharacterEncoding("utf-8"); //只对post有效
response.setContentType("text/html;charset=utf-8");
DiskFileItemFactory factory = new DiskFileItemFactory(); //处理文件的工厂
ServletFileUpload upload = new ServletFileUpload(factory); //文件对象
// 上传文件的大小
upload.setFileSizeMax(64* 1024 * 1024);
// 设置上传文件大小,总大小,包括文件和表单
upload.setSizeMax(128 * 1024 * 1024);
try {
@SuppressWarnings("unchecked")
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){
String name = fileItem.getFieldName();
String value = fileItem.getString("utf-8");
System.out.println(name + "=" + value);
}else{
String fileName = fileItem.getFieldName();//获得文件名
fileItem.write(new File("c:/", fileName));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
PrintWriter printWriter = response.getWriter();
printWriter.print("你的文件上传完毕");
printWriter.flush();
文件上传客户端:
String url = "";
HttpClient client = new DefaultHttpClient();
MultipartEntity entity = new MultipartEntity();
FileBody body = new FileBody(new File(""));
FormBodyPart bodyPart = new FormBodyPart("form.exe", body);
entity.addPart(bodyPart);
HttpPost post = new HttpPost(url);
post.setEntity(entity);
HttpResponse response = client.execute(post);
- 单元测试
第一步:
AndroidManifest文件:
1. <uses-library android:name="android.test.runner"/>代表把单元测试框架中的一些依赖库引入进来
2. <instrumentation android:name="android.test.InstrumentationTestRunner"android:targetPackage="com.pccw" />代表配置单元测试框架的启动装置,启动装置有好几个类,可以选择,一般情况下我们使用上面这个。
3. targetPackage与上面的package相同,代表单元测试框架和当前应用是处于同一个进程中
第二步:编写测试代码。类内写测试方法
public class extends AndroidTestCase {
}