.Net码农学Android---快速了解数据存储
数据存储
Andoid中的数据存储和我们平时见到的不一样,或者说移动设备的存储和平时不一样。Andoid中的存储方式有五种, 单把存储拎出来,是因为我们后续的开发会经常用到,重要性不言而喻,多样的存储方式让我们选择时更加灵活,但每种方式都有各自的应用场景,不可相互替代,请看:
方式一:Shared Preferences
你可以叫它用户偏好参数,顾名思义,就是用来存储一些用户的自定义设置,或其它“微型"用户数据
等等,好像忘了一件事,很重要,很重要! 下面请按我说的做:
拿出你的Android手机
- 打开R.E管理器(什么?没有,还不快戳我)
- 查看文件
如果经常查看文件的同学肯定发现了这么一个奇怪的现象
这三个路径里的文件竟然一模一样,搞毛啊!
其实真相是这样的
这个概念一定要明确,接着返回根目录,在/data/data/<包名>/...中(随便打开一个包),会看到有/lib,/shared_prefs,/files,等几个文件夹,我们的sharedPreferencesfan方式所存储的文件位置就在/shared_prefs中,读写例子大家就自己找吧,对不住了!
这里面提到的这几个文件夹会经常用到,大家一定要熟悉!
方式二:文件存储
这里的文件存储其实又可以分为两种
存储到系统默认位置
先看代码
/*name 文件名,只是名字,不包含路径,如love
/*content 内容
public void save(String name, String content) {
try {
FileOutputStream outputStream = context.openFileOutput(name,Context.MODE_WORLD_WRITEABLE + Context.MODE_WORLD_READABLE);
outputStream.write(content.getBytes());
outputStream.close(); } catch (Exception e) {
// TODO: handle exception
} }
注意看代码中的注释,指定了文件名后,会默认存储到之前的/data/data/<包名>/files/<name>,格式默认xml,即是k/v的形式。
存储到自定义位置
public void saveToSdcard(String filename,String content) throws Exception{
File file=new File("/storage/sdcard0",filename);
FileOutputStream outputStream=new FileOutputStream(file);
outputStream.write(content.getBytes());
outputStream.close(); }
可以指定文件位置,比较灵活,但个人建议还是遵守Android的约定,即使用默认存储位置,便于管理维护,结构也比较清晰。
方式三:SqlLite数据库存储
SqlLite简介,请走此通道,Android中内嵌了SqlLite,所以使用部署时不用安装数据库什么的了。
SqlLite场景适合于那些数据比较庞大,复杂的数据存储,并且也有相关的Gui。
先看段代码:
public class DbOpenHeler extends SQLiteOpenHelper {// 需手动实现一下构造方法 public DbOpenHeler(Context contet) { super(contet, "itcast.db", null, 3);//传入版本号
} public DbOpenHeler(Context context, String name, CursorFactory factory,
int version) {
super(context, "itcast.db", null, 1);
// TODO Auto-generated constructor stub
} @Override
public void onCreate(SQLiteDatabase db) {
// 第一次创建时会执行
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE person(personId integer primary key autoincrement,name varchar(20))"); } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub//当版本号不一样时即升级时会执行
//db.execSQL("ALTER TABLE person ADD phone varchar(20) null");
db.execSQL("ALTER TABLE person ADD amount integer");
} }
看到OnCreate和OnUpgrade了吗,这两个方法必须给实现了。
OnCreate()在初始化你自定义的数据库时会调用,你必须给它指定一个版本号,用来标识。
OnUpgrade()的作用是:当我们由于需求需要修改数据库或升级数据库时,只需在构造方法中重新写入一个新的版本号(和之前的版本号不同),系统就会检测到不同从而调用OnUpgrade(),你只需把你要改的加入到OnUpgrade()中就ok了
具体SqlLite操作实例,请看http://www.cnblogs.com/cczw/archive/2012/05/23/2514544.html
方式四:ContentProvider
这是一种共享数据的存储方式,当你的一些数据需要暴露给其他调用者时就要用用到这个了。
有些同学可能会说,我可以把数据放在文件中,比如方式一中的路径下不也可以访问吗?不可以,安卓中非常注重用户的安全性,所以很多操作都被加上了权限的验证,方式一中的路径下的文件默认是只能让本应由访问的, (采用公开写入权限可以访问),同时也统一了应用间共享数据访问方式。
同时,Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。
首先来明确几个概念
概念一.Uri(统一资源标识符)
为系统的每一个资源给其一个名字,比方说通话记录。
1、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。
2、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:
A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
B:URI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称;"content://com.android.text.myprovider"
C:路径,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就ok了;"content://com.android.text.myprovider/tablename"
D:参数,如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;"content://hx.android.text.myprovider/tablename/#" #表示数据id
概念.二UriMatcher、ContentUrist和ContentResolver
因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.letchoice.providers.personprovider路径,返回匹配码为1
uriMatcher.addURI(“com.letchoice.providers.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配 content://com.letchoice.provider.personprovider/person/230路径,返回匹配码为2
uriMatcher.addURI(“com.letchoice.providers.personprovider”, “person/#”, 2);//#号为通配符
2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.letchoice.provider.personprovider/person路径,返回的匹配码为1。
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
• withAppendedId(uri, id)用于为路径加上ID部分
• parseId(uri)方法用于从路径中获取ID部分
ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。
接下来看个例子吧:
Step1:定义你的Provider类
public class MyContentProvider extends ContentProvider {
private DbOpenHeler dbOpenHeler;//之前的SqlLite helper类
}
Step2:定义你的Uri
private DbOpenHeler dbOpenHeler;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);//定义一个Matcher // private static final int PERSON = 1;
// private static final int PERSON = 2;
public enum PERSON {
// 自定义枚举参数值
INSERT(1), DELETE(2);
private int nCode; private PERSON(int nCode) {
this.nCode = nCode;
} @Override
public String toString() {
// TODO Auto-generated method stub
return String.valueOf(this.nCode);
} };
//这里是你定义的Uri,分两种,一种不带参数,一种带参数
static {
MATCHER.addURI("com.letchoice.providers.personprovider", "person",Integer.parseInt(PERSON.INSERT.toString()));
MATCHER.addURI("com.letchoice.providers.personprovider", "person/#",Integer.parseInt(PERSON.DELETE.toString()));
}
Step3:在AndroidManifest.xml当中进行声明
<provider
android:name=".MyContentProvider"
android:authorities="com.letchoice.providers.personprovider" >
</provider>
Step4:实现CURD方法(只贴一个query的)
@Override
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteDatabase db = dbOpenHeler.getReadableDatabase();
switch (MATCHER.match(uri)) {//匹配检测
case 1://如果uri不带参数就不带参数查询
return db.query("person", projection, selection, selectionArgs,null, null, sortOrder); case 2://如果uri带参数就带参数查询
long rid = ContentUris.parseId(uri);
String where = "personId=" + rid;
if (selection != null && !"".equals(selection.trim())) {
where += "and" + selection;
}
return db.query("person", projection, where, selectionArgs, null,null, sortOrder);
default:
throw new IllegalArgumentException("this is Unknown Uri" + uri);
} }
Step5:外部调用query得到你想要的结果
public void testQuery() {
Uri uri=Uri.parse("content://com.letchoice.providers.personprovider/person");
ContentResolver resolver=this.getContext().getContentResolver();//使用ContentResolver解析uri
Cursor cursor=resolver.query(uri, null, null, null,"personId asc");//按照personId升级排序
cursor.moveToFirst();
while (cursor.moveToNext()) {
Log.i("testQuery",cursor.getString(cursor.getColumnIndex("name")));//打印出结果
}
cursor.close(); }
方式五:网络获取
前面介绍的几种存储都是将数据存储在本地设备上,除此之外,还有一种存储(获取)数据的方式,通过网络来实现数据的存储和获取。
我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。
具体需要熟悉java.net.*,Android.net.*这两个包的内容,在这就不赘述了,请大家参阅相关文档。
下面是一个通过地区名称查询该地区的天气预报,以POST发送的方式发送请求到webservicex.net站点,访问WebService.webservicex.net站点上提供查询天气预报的服务。
package com.android.weather; import java.util.ArrayList;
import java.util.List; import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils; import android.app.Activity;
import android.os.Bundle; public class MyAndroidWeatherActivity extends Activity {
//定义需要获取的内容来源地址
private static final String SERVER_URL =
"http://www.webservicex.net/WeatherForecast.asmx/GetWeatherByPlaceName"; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); HttpPost request = new HttpPost(SERVER_URL); //根据内容来源地址创建一个Http请求
// 添加一个变量
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 设置一个地区名称
params.add(new BasicNameValuePair("PlaceName", "NewYork")); //添加必须的参数 try {
//设置参数的编码
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
//发送请求并获取反馈
HttpResponse httpResponse = new DefaultHttpClient().execute(request); // 解析返回的内容
if(httpResponse.getStatusLine().getStatusCode() != 404){
String result = EntityUtils.toString(httpResponse.getEntity());
System.out.println(result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
别忘记了在配置文件中设置访问网络权限:<uses-permission android:name="android.permission.INTERNET" />
部分内容参考:
http://www.cnblogs.com/chenglong/articles/1892029.html
http://blog.sina.com.cn/s/blog_5688414b0100xagp.html
http://www.cnblogs.com/hanyonglu/archive/2012/03/01/2374894.html
.Net码农学Android---快速了解数据存储的更多相关文章
- 67.Android中的数据存储总结
转载:http://mp.weixin.qq.com/s?__biz=MzIzMjE1Njg4Mw==&mid=2650117688&idx=1&sn=d6c73f9f04d0 ...
- Android Learning:数据存储方案归纳与总结
前言 最近在学习<第一行android代码>和<疯狂android讲义>,我的感触是Android应用的本质其实就是数据的处理,包括数据的接收,存储,处理以及显示,我想针对这几 ...
- Android中的数据存储
Android中的数据存储主要分为三种基本方法: 1.利用shared preferences存储一些轻量级的键值对数据. 2.传统文件系统. 3.利用SQLite的数据库管理系统. 对SharedP ...
- Android五种数据存储方式
android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...
- Android中的数据存储(二):文件存储 2017-05-25 08:16 35人阅读 评论(0) 收藏
文件存储 这是本人(菜鸟)学习android数据存储时接触的有关文件存储的知识以及本人自己写的简单地demo,为初学者学习和使用文件存储提供一些帮助.. 如果有需要查看SharedPreference ...
- Android下的数据存储与訪问 --- 以文件的形式
Android下的数据存储与訪问 --- 以文件的形式 1.1 储存文件存放在手机内存中: // *** 储存数据到 /data/data/包名/files/jxn.txt文件里 String dat ...
- Android——几种数据存储应用浅谈
(1)android中的数据存储主要有五种方式: 第一种.sharedPreferences存储数据, 适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配 ...
- android下的数据存储
android下数据存储的几种方式:(简单讨论) 1.文件 举例:登陆时“记住密码” 因为是基于Linux系统,直接建文件,文件会出现在项目工程:而手机登陆时,应该把文件放在手机里,通常数据放在dat ...
- Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用
前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...
随机推荐
- MongoDB基本操作命令
由于工作需要,笔者这两天使用了一下MongoDB.真的很不习惯!但是确实好用,命令比mysql和sqlserver简单很多.在这里整理一些MongoDB的基本操作命令分享出来. 客户端的安装就不说了, ...
- cygwin中运行命令提示command not found的解决方法
在cygwin下运行ls等linux常见命令时出现“command not found”的提示,原因是环境变量没有配置好,因此只要将环境变量配置正确,即可正常使用.举例说明,cygwin安装在C盘根目 ...
- 学习记录 java 链表知识
01.import java.util.HashMap; 02.import java.util.Scanner; 03.import java.util.Stack; 04. 05./** 06. ...
- Sass基础语法
Sass是CSS3语言的扩展,在CSS的基础之上添加了新特性和语法,能省事地写出更好的样式表.Sass引擎是基于Ruby的. 导入Sass文件: @import "colors" ...
- 用PHP实现守护进程任务后台运行与多线程(php-resque使用说明)
消息队列处理后台任务带来的问题 项目中经常会有后台运行任务的需求,比如发送邮件时,因为要连接邮件服务器,往往需要5-10秒甚至更长时间,如果能先给用户一个成功的提示信息,然后在后台慢慢处理发送邮件的操 ...
- Jmeter笔记2:参数化(五种方法)
案例:邮箱登录操作,参数化登录的用户名 方法一.依赖Jmeter自带的函数助手 选项-->函数助手对话框,即可打开函数助手弹窗 (1)比如使用函数_Random 输入最小值.最大值,点击下方的[ ...
- 解读CSS布局之-水平垂直居
对一个元素水平垂直居中,在我们的工作中是会经常遇到的,也是CSS布局中很重要的一部分,本文就来讲讲CSS水平垂直居中的一些方法.由于我们大搜车的日常工作中已经不再需要理会低版本IE,所以本文所贴出的方 ...
- .net 调用SAP RFC函数获取数据的两种方式
方式1:使用客户端自带的组件 安装客户端以后,添加引用:SAPFunctionsOCX(.net 的Com列表里一般找不到,需要引用DLL[一般位于以下路径:Program Files\SAP\Fro ...
- linux 下wifi 功能的实现
一.嵌入式linux四件套配置 1.网卡选型的依据: a.网卡不能乱选,否则没戏.网卡的依据是,kernel的menuconfig -> device drivers -> network ...
- MyEclipse中使用debug调试程序
最基本的操作是: 1.首先在一个java文件中设断点,然后debug as-->open debug Dialog,然后在对话框中选类后--> Run 当程序走到断 ...