Android学习之路(5)——数据存储方式

Android系统中的数据存储区方式有五种:

五种数据存储方式

1.文件存储:以I/O流的形式把数据存入手机内存或SD卡,可以存储大数据。

2.SharedPreference:本质是一个XML文件,以Map<Object,Object>形式存入手机内存中。

3.SQLite数据库:SQLite是一个轻量级、跨平台的数据库。数据库中所有信息都存储在单一文件内,占用内存小,并且支持SQL语法,通常用于存储用户信息。

4.ContentProvider:内容提供者,是Android四大组件之一,以数据库形式存入手机内存,可以共享自己的数据给其他应用使用。

5.网络存储:把数据存储到服务器,不存储在本地,使用的时候直接从网络获取。

文件存储

1.内部存储:将应用程序中的数据以文件形式存储到设备的内部存储空间中,内部存储方式存储的文件被其所创建的应用程序私有。

内部存储使用的是Context提供的openFileOutput()方法和openFileInput()方法,分别获取FileOutputStream对象和FileInputStream对象。

参数name表示文件名
mode表示文件的操作模式
MODE_PRIVATE:该文件只能被当前程序读写,默认操作模式
MODE_APPEND:该文件可以追加内容,常用模式
MODE_WORLD_READABLE:该文件的内容可以被其他文件读取,安全性低。
MODE_WORLD_WRITEABLE:该文件的内容可以被其他程序写入,安全性低。

存储数据:

String fileName="data.txt";//文件名称
String content="helloworld";//保存数据
FileOutPutStream fos;
try{
    fos=openFileOutput(FileName,MODE_PRIVATE);
    fos.write(content.getBytes());
    fos.close();
    }catch(Exception e){
    e.printStackTrace();
    }

取出数据:

String Content="";
FileInputStream fis;
try{
    fis=openFileInput("data.txt");
    byte[] buffer=new byte[fis.available()];
    fis.read(buffer);
    content=new String(buffer);
    }catch(Exception e){
    e.printStackTrace();
    }

2.外部存储:将文件存储到一些外围设备上。
由于外围存储设备可能被移除、丢失、或者出其他状态,因此在使用外围设备之前必须使用Environment.getExternalStorageState()方法来确认外围设备是否可用。通过FileInputStream、FileOutputStream或者FileReader、FileWriter对象来读写外围设备中的文件。

从外围设备存储数据:

String state=Environment.getEcternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
    File SDPath=Environment.getExternalStorageDriectory();
    File file=new File(SDPath,"data.txt");
    String data="HelloWorld";
    FileOutputStream fos;
    try{
        fos=new FileOutputStream(file);
        fos.write(data.getBytes());
        fos.close();
        }catch(Exception e){
        e.printStackTrace();
        }

从外围设备中读取数据:

String state=Environment.getExternalStorageState();
if(State.equals(Environment.MEDIA_MOUNTED)){
    File SDPath=Environment.getExternalStorageDirectory();
    File file=new File(SDPath,"data.txt");
    FileInputStream fis;
    try{
        fis=new FileInputStream(file);
        BufferedReader br=new BufferedReader(new InputStreamReader(fis));
        String data=br.readLine();
        fis.close();
        }catch(Exception e){
        e.printStackTrace();
        }
    }

SharedPerferences

是Android平台上以个轻量级的存储类,主要用于存储一些应用程序的配置参数。SharedPerference中存储的数据是以key/value键值对的形式保存在XML文件中,该文件位于data/data/<packagename>/shared_prefs 文件夹中。需要注意的是,SharedPerferences中的value只能是float、int、long、boolean、String、StringSet类型。

使用SharedPerferences类存储数据时,首先需要通过context.getSharedPerferences获取SharedPerferences的实例对象。
(PS:SharedPreferences对象本身只能获取数据,并不支持数据的存储和修改)
数据的存储和修改需要通过SharedPerferences.Editor()对象实现。

通过Editor对象相关方法存储数据:

SharedPerferences sp=getSharedPerferences("data",MODE_PERIVATE);
Eidtor editor=sp.edit();// 获取编辑器
editor.putString("name","小白");//存入String类型数据
editor.putInt("age",8);//存入Int类型数据
editor.commit();//提交修改

使用对象获取相应的key值即可:

SharedPerferences sp=context.getSharedPreferences();
String data=sp.getString("name","");//获取用户名

通过该对象删除数据:

SharedPerferences sp=context.SharedPerferences();
Editor editor=sp.edit();
editor.remove("name");//删除一条数据
editor.clear();
editor.commit();

SQLite数据库

SQLite遵循ACID关联的数据库管理系统。
ACID:原子性,一致性,隔离性,持久性。

SQLite没有服务进程,通过文件保存数据,该文件是跨平台。
支持NULL,INTEGER,REAL,TEXT,BLOB.
实际上SQLite也接受varchar,char,decimal等数据类型。
只不过在运算或保存时转换成对应的五种数据类型。

1.创建SQLite数据库

public class PersonSQLiteOpenHelper extends SQLiteOpenHelper{
    //数据库的构建方法,用来定义数据库的名称,数据库查询的结果,数据库的版本
    public PersonSQLiteOpenHelper(Context context){
    super(context,"person.db",null,5);
    }
    //数据库第一次被创建时调用该方法
    public void OnCreate(SQLiteDatabase db){
    //初始化数据库的表结构,执行一条键表的SQL语句
    db.execSQL("create table person(
        id integer primary key autoincrement,"+
        "name varchar(20),"+
        "number varchar(20)");
    }
    //当数据库的版本号增加时调用
    public void onUpgrade(SQLiteDatabase db,int oldVesion, int newVersion){
    db.execSQL("alter table person  add account varchar(20);
    }
}

2.添加数据

public long add(String name,String number){
    //拿到一个读写的SQLiteDatabase对象
    SQLiteDatabase db=helper.getWritableDatabase();
    //将参数名和列添加到ContentValues对象里面
    ContentValues values=new ContentValues();
    values.put("name",name);
    values.put("number",number);
    //输入数据到person表里
    long id=db.insert("person",null,values);
    //关闭数据库
    db.close();
    return id;

db.execSQL(“insert into person(name ,number) value(?,?)”,new Object[]{name,number})
3.修改数据

public int update(String name,String newnumber){
    //拿到一个读写的SQLiteDatabase对象
    SQLiteDatabase db=helper.getWritableDatabase();
    //将参数名和列添加到ContentValues对象里面
    ContentValues values=new ContentValues();
    //将参数以key,values
    values.put("number",newnumber);
    //输入数据到person表里
    int number=db.update("person",values,"name=?",new String []{name});
    //关闭数据库
    db.close();
    return id;

4.删除数据

public int delete(String name){
    //拿到一个读写的SQLiteDatabase对象
    SQLiteDatabase db=helper.getWritableDatabase();
    //删除数据
    int number=db.delete("person","name=?",new String []{name});
    //关闭数据库
    db.close();
    return number;

5.查询数据

public boolean find(String name){
    //获取一个可读的数据库
    SQLiteDatabase db=helper.getReadableDatabase();
    //查询数据库的操作  参数1:表名,参数2:查询的列名,参数3:查询条件
    //参数4:查询参数值,参数5:分组条件 参数6:having条件,参数7:排列方式
    Cursor cursor=db.query("person",null,"name=?",new String[] {name},null,null,null);
    //是否有下一条值
    boolean result=cursor.moveToNext();
    //关闭游标
    cursor.close();
    //关闭数据库
    db.close();
    return result;
}

rawQuery()方法执行SQL语句
Cursor cursor=db.rawQuery(“select * from person where name=?”,new String []{name});

5.SQLite事务操作

PersonSQLiteOpenHelper helper =new PersonSQLiteOpenHelper(getContext());
    //获取一个可写的SQLiteDatabase
    SQLiteDatabase db=helper.getWritableDatabase();
    //开始数据库的事务
    db.beginTransaction();
    try{
    //执行转出操作
    db.execSQL("update person set account=account-1000 where name=?",new Object[]{"zhangsan"};

    //执行转入操作
    db.execSQl("update person set account=account+1000 where name=?",new Object []{"wangwu"});
    //标记数据库事务执行成功
    db.setTransactionSuccessful();
    }catch(Exception e){
        Log.i("事务处理失败",e.toString());
    }finally{
        db.endTransaction();//关闭事务
        db.close();//关闭数据库
    }
}

ContentProvider

是Android系统四大组件之一,用于保存和检索数据,是android系统中不同应用程序之间共享数据的接口。

是不同应用程序之间进行数据交换的标准API,以Uri的形式对外提供数据,允许其他应用操作本应用数据。

1.创建内容提供者
首先定义一个类继承android.conten包下的ContentProvider类。在使用该类时需要重写它的onCreate()、delete()、getType()、insert()、query()、update()这几个抽象方法。

如果指定数据的类型属于集合型,getType()方法返回的字符串应该以“vnd.android.cursor.dir/”开头。

如果属于非集合类型则返回的字符串以“vnd.android.cursor.item/”.

创建者内容提供:

public class PersonDBProvider extends ContentProvider{
    public boolean onCreate(){
        return false;
    }
    public Cursor query(Uri uri,String [] projection,String selection,String [] selectionArgs,String sortOrder){
        return null;
    }
    public String getType(String uri){
        return null;
    }
    public Uri insert (Uri uri,ContentValues values){
        return null;
    }
    public int delete(Uri String selection ,String [] selectionArgs){
        return 0;
    }
    public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
    return 0;
    }
}

注册内容提供者:

<provider
    android:name="cn.itcast.db.PersonDBProvider"
    android:authorities="cn.itcast.db.personprovider">
</provider>

当使用provider暴露敏感的数据时,为了数据安全,在注册ContentProvider时,还可以为其指定权限。
android:permission属性:如果注册provider时使用了该属性,那么其他程序在访问ContentProvider时必须加上权限,否则会报异常。
例如:
PersonDBProvider注册了android:permission=”mobile.permission android:name=”mobile.permission.PROVIDER”,那么在其他应用使用该provider时需要加上权限
android:readPermission属性:如果注册provider时使用了该属性,那么其他应用程序通ContentProvider的query()方法查询数据时,必须加上该权限。
android:writePermission属性:如果在注册provider时使用该属性,那么其他应用程序通过ContentProvider的增、删、改这几个方法操作数据时,必须加上权限。
(注意:在注册provider时,为其指定自定义权限。为了让自定义权限生效,首先单机清单文件中permission标签页的Add标签。)

Uri

在ContentProvider的几个抽象方法中,其中有一个参数Uri uri,它代表了数据的操作方法。
Uri时由scheme,authorites,path三部分组成。
示例:content://(scheme)cn.itcast.db.personprovider(authorities)/person(path)
shcme部分content://是一个标准前缀,表明数据被内容提供者所控制,不会被修改。
authorities部分cn.itcast.db.personprovider是在清单文件中指定的android:authorities属性值,该值必须唯一,表示当前的内容提供者。
path部分/person代表资源,当访问者需要不同数据时,这个部分是动态改变的。

访问内容提供者

ContentResolver的基本用法:
通过ContentProvider暴露自己的数据,通过ContentResoler对应用程序暴露的数据进行操作。在使用ContentProvider暴露数据时提供相应的操作Uri,因此在访问现有的ContentProvider时要指定相应的Uri,然后通过ContentResolver对象实现。

//获取相应操作的Uri
Uri uri=Uri.parse("content://cn.itcast.db.personprovider/person");
//获取到ContentReolve对象
ContentResolver resolve=context.getContentResolver(0;
//通过ContentResolver对象查询数据
Cursor cursor=resolver.query(uri,new String []{"address","date","type","body"},null,null,null);
while(Cursor.moveToNext()){
    String address=cursor.getString(0);
    long date=cursor.getlong(1);
    int type=cursor.getInt(2);
    String body=cursor.getString(3);
}
cursor.close();

内容观察者

用来观察指定Uri所代表的的数据。当ContentObserver观察到指定Uri所代表的数据。当ContentObserver观察到指定Uri代表的数据发生变化时,就会触发ContentObserver的onChange()方法。此时在onChange()方法里用ContentResolver可以查到变化的数据。

public void ContentObserver(Handle handle//ContentObsever的派生类都需要调用该构造方法。参数可以是主线程Handle,也可以是任何Handle对象
public void onChange(boolean selfChange)
//当观察到的Uri代表的数据发生变化时,会触发该方法

如果使用Contentobsever观察数据变化,就必须在ContentProvider中的delete(),insert(),update()方法中调用ContentResolver的notifyChange()方法。

//添加数据
public Uri insert(Uri uri,ContentValues values){
    if(matcher.math(uri)==INSERT){//匹配Uri路径
    //匹配成功,返回查询结果
    SQLiteDatabase db=helper.getWritableDatabase();
    db.insert("person",null,values);
    getContext().getContentResolver().notifyChange(PersonDao.messageuri,null);
}else{//匹配成功
    throw  new IllegalArgumentException("路径不匹配,不能执行插入操作");
}
return null;

网络存储

HttpUrlConnection是Java.NET包中提供的API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:
1、将访问的路径转换成URL。

URL url = new URL(path);

2、通过URL获取连接。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、设置请求方式。

conn.setRequestMethod(GET);

4、设置连接超时时间。

conn.setConnectTimeout(5000);

5、设置请求头的信息。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

 HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了。
HttpClient发送GET请求

1、 创建HttpClient对象

2、创建HttpGet对象,指定请求地址(带参数)

3、使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象

4、调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

5、调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

public static String loginByHttpClientGet(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
                + username + &password= + password;
        HttpClient client = new DefaultHttpClient(); // 开启网络访问客户端
        HttpGet httpGet = new HttpGet(path); // 包装一个GET请求
        try {
            HttpResponse response = client.execute(httpGet); // 客户端执行请求
            int code = response.getStatusLine().getStatusCode(); // 获取响应码
            if (code == 200) {
                InputStream is = response.getEntity().getContent(); // 获取实体内容
                String result = StreamTools.streamToString(is); // 字节流转字符串
                return result;
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 网络访问失败;
        }
    }

HttpClient发送POST请求

1,创建HttpClient对象

2,创建HttpPost对象,指定请求地址

3,创建List,用来装载参数

4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数

5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象

6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

public static String loginByHttpClientPOST(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
        try {
            HttpClient client = new DefaultHttpClient(); // 建立一个客户端
            HttpPost httpPost = new HttpPost(path); // 包装POST请求
            // 设置发送的实体参数
            List parameters = new ArrayList();
            parameters.add(new BasicNameValuePair(username, username));
            parameters.add(new BasicNameValuePair(password, password));
            httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
            HttpResponse response = client.execute(httpPost); // 执行POST请求
            int code = response.getStatusLine().getStatusCode();
            if (code == 200) {
                InputStream is = response.getEntity().getContent();
                String result = StreamTools.streamToString(is);
                return result;
            } else {
                return 网络访问失败;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 访问网络失败;
        }
    }

参考:

  Android开发请求网络方式详解。

猜你喜欢

转载自blog.csdn.net/waitwolf/article/details/70568801