Android数据存储的五种方式

使用SharedPreferences存储数据

介绍: 它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。


获得SharedPreferences对象的方式

  • 通过Context的getSharedPrerences(key, [模式])方法获取SharedPreferences对象。
    方法的第一个参数是用于指定SharedPreferences文件的名称,第二个参数是指定操作模式。
    主要有两种模式进行选择:MODE_PRIVATE(默认操作模式), MODE_MULTI_PROCESS;
  • 通过Activity类提供的getPrerences(key)方法获取到SharedPreferences对象,该方法会创建一个以当前活动类名作为SharedPreferences文件名的文件;
  • 通过PreferencesManager类中的getDefaultPreferernces()方法获得,这是一个静态的方法,他接收一个Context参数,并将当前应用程序的包名作为SharedPreferences文件名。

写数据

// key = "gjcData",也就是数据存储在data/data/程序包名/shared_prefs目录下的gjcData.xml文件下
// 获取SharedPreferences对象
SharedPreferences preferences = getSharedPreferences("gjcData", MODE_PRIVATE);
// 使用SharedPreferences的editor()方法获取Editor对象
SharedPreferences.Editor editor = preferences .edit();
// 通过Editor的putXXX()方法以键值对形式存储数据
editor.putString("name", "是阿超");
// 通过Editor的commit()方法提交数据
editor.commit();

读数据

// 获取SharedPreference对象
SharedPreferences preferencesOutput = getSharedPreferences("gjcData", MODE_PRIVATE);
// 通过SharedPreference对象的getXXX方法获取数据(第一个参数是要获取的值的key,第二个参数是如果键值不存在返回的默认的XXX类型的值)
String content = preferencesOutput.getString("name", "");

Editor的commit()提交数据和apply()提交数据的区别

  • commit和apply虽然都是原子性操作,但是原子的操作不同。
    commit是原子提交到数据库,从提交数据到存在磁盘中都是同步过程;
    而apply方法的原子操作是原子提交到内存中而非数据库,之后再异步提交数据到数据库中。
  • commit提交是同步过程,效率会比apply异步提交的速度慢,有返回值;
    apply没有返回值,无法知道存储是否失败。

(在不关心提交结果是否成功的情况下,优先考虑apply方法)

文件存储数据

介绍: 文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。


文件存储分为两种:内部存储和外部存储

  • 内部存储:指Android为应用程序分配的内存(不需要任何权限)
  • 外部存储:手机的内存空间,手机内置sd卡(需要加入读写外部存储权限)

内部存储

通过Context类中的输入流和输出流获取/data/data//files目录下存储的数据

files目录下写数据
FileOutputStream fileOutputStream;
PrintWriter writer;
try {
		// 通过Context的openFileOutput(String filename, int mode)方法拿到数据流(第一个参数是在/data/data//files目录下存储的文件名,第二个参数是文件的操作模式)
		fileOutputStream = openFileOutput("gjcData", MODE_PRIVATE);
		writer = new PrintWriter(new OutputStreamWriter(fileOutputStream));
		writer.write("Hello world");
		writer.flush();//刷新流
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		writer.close();
		fileOutputStream.close();
	}
files目录下读数据
FileInputStream fileInputStream;
BufferedReader bufferedReader;
try {
		// 通过Context的 openFileInput(String filename)方法拿到数据流(参数为/data/data//files目录下需要读取的文件名)
		fileInputStream = openFileInput("gjcData");
		bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
		String line = bufferedReader.readLine();
		while (line != null) {
			Log.d("data", "" + line);
			line = bufferedReader.readLine();
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		bufferedReader.close();
		fileInputStream.close();
	}

通过Context类中的getCacheDir()方法获取/data/data//cache目录创建相关的文件存储数据

cache目录下写数据
// 创建/data/data/<package name>/cache/gjcData文件对象
FileOutputStream fos;
PrintWriter writer;
File file = new File(getCacheDir(), "gjcData");
if (!file.exists()) {
	try {
		file.createNewFile();//如果文件不存在,则创建
		fos = new FileOutputStream(file);
		writer = new PrintWriter(new OutputStreamWriter(fos));
		writer.write("Hello world");
		writer.flush();
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		writer.close();
		fos.close();
	}
}
cache目录下读数据
FileInputStream fis;
BufferedReader br;
File file = new File(getCacheDir(), "gjcData");
try {
	fis = new FileInputStream(file);
	br = new BufferedReader(new InputStreamReader(fis));
	String line = br.readLine();
	while(line!=null){
		line = br.readLine();
	}
} catch (Exception e) {
	e.printStackTrace();
} finally {
	br.close();
	fis.close();
}

外部存储

添加权限

<!-- 允许程序写入外部存储-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

写数据

FileOutputStream fos;
BufferedWriter bw;
// 创建gjcData文件对象,由于不同手机SDcard目录不同,所以我们通过Environment.getExternalStorageDirectory()获取路径
File file = new File(Environment.getExternalStorageDirectory(), "gjcData");
if (!file.exists()){
	try {
		file.createNewFile();
	} catch (Exception e) {
		e.printStackTrace();
	}
}
try {
	fos =new FileOutputStream(file);
	bw = new BufferedWriter(new OutputStreamWriter(fos));
	bw.write("Hello world");
	bw.flush();
} catch (Exception e) {
	e.printStackTrace();
} finally {
	bw.close();
	fos.close();
}

读数据

FileInputStream fis;
BufferedReader br;
File file = new File(Environment.getExternalStorageDirectory(), "gjcData");
try {
	fis = new FileInputStream(file);
	br =  new BufferedReader(new InputStreamReader(fis));
	String line = br.readLine();
	while(line!=null){
		line = br.readLine();
	}
} catch (Exception e) {
	e.printStackTrace();
} finally {
	br.close();
	fis.close();
}

SQLite数据库存储数据

介绍: SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库


数据库的操作借助于SQLiteOpenHelper,SQLiteOpenHelper是一个抽象类,所以我们在使用SQLiteOpenHelper时要先创建一个MySQLiteOpenHelper类继承SQLiteOpenHelper


SQLiteOpenHelper有两个比较重要的方法

  • getReadableDatabase()方法返回数据库是一个只读的;
  • getWriteableDatabase()方法获得是一个可读写的数据库对象。

创建一个MySQLiteOpenHelper

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

     // 构造器,传入四个参数(Context上下文环境,String数据库名字,CursorFactory操作数据库的Cursor对象(通常为null),int数据库版本号) 
    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    
    // 自定义的构造器
    public MySQLiteOpenHelper(Context context, String name) {
        this(context, name, null, 1);//传入Context和数据库的名称,调用上面的构造器
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        // 在创建数据库时,创建一个user数据表
        String sql = "create table if not exists user(id integer primary key  autoincrement, name varchar(20), password varchar(20))";
        sqLiteDatabase.execSQL(sql);
    }
    
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    	//用于修改数据库版本(第一个参数是SQLiteDatabase对象,第二个参数是旧的版本号,第三个参数是新版本号。一般我们在这个方法里边删除数据库表,并建立新的数据库表)
    }
}

使用MySQLiteOpenHelper进行增删改查

// 创建数据库(数据库名称为myDataDb)
MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(getApplicationContext(), "myDataDb");
SQLiteDatabase db = mySQLiteOpenHelper.getWritableDatabase();

// 增(SQLite的添加语句:INSERT INTO user (name, passwords)] VALUES ("张三", "123456"))
ContentValues value = new ContentValues();//用于存储数据
value.put("name", "阿超");//向数据表中字段名为name的字段中添加"阿超"
value.put("password", "123456");//向数据表中字段名为passwords的字段中添加"123456"
// db数据库对象在前面已经创建,这里直接使用
db.insert("user",null, value);//在数据库的user数据表中添加字段名name为"阿超",字段名passwords为"123456"的数据

// 删(SQLite的删除语句:DELETE FROM user WHERE name = "张三")
db.delete("user", "name=?", new String[]{"张三"});//第一个参数表名,第二个参数条件,第三个参数为对应的删除条件

// 改(SQLite的修改语句:UPDATE user SET passwords= "666" WHERE name="张三")
ContentValues values = new ContentValues();
values.put("password", "666");
db.update("user", values, "name=?", new String[]{"张三"});(把名字为张三的密码修改为666// 查(SQLite的查询语句:SELECT * FROM user)
String sql = "select * from user";
Cursor cursor = db.rawQuery(sql, null);
cursor.moveToFirst();//转移到结果的第一行
while(!cursor.isAfterLast()){
	String name = cursor.getString(cursor.getColumnIndex("name"));
	String passwords = cursor.getString(cursor.getColumnIndex("password"));
	LogUtil.i("data", "name=" + name + "   password=" + passwords);
	cursor.moveToNext();
}

使用ContentProvider存储数据

介绍: 内容提供器,主要用于在不同应用程序之间实现数据的共享,从而能够让其他的应用保存或读取此Content Provider的各种数据类型


ContentProvider使用方法有两种

  • 使用现有的内容提供器来读取和操作相应程序中的数据
  • 创建自己的内容提供器给我们的应用提供外部访问接口

使用ContentResolver读取数据

在ContentResolver中是通过Uri指定操作的内容“位置”


Uri由两部分组成:权限和路径

  • 权限是对于不同的应用程序进行区分的,一般用应用程序的包名;
  • 路径是对于同一应用程序的不同表进行区分的。
    例如,我们有一个应用程序的包名是“top.gaojc.demo”,应用程序中有一个表是table,则Uri为:content://top.gaojc.demo/table
    (Uri uri = Uri.parse.(“content://top.gaojc.demo/table”);)
<!--允许读取通讯录 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
ContentResolver mContentResolver= getContentResolver();

/**
* 增删改的方式和SQLite存储方式类似,这里不再进行过多阐述
*/

// 查(查询通讯录为例,查询通讯录需要添加上方权限)
Cursor cursor = mContentResolver.query(uri,new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
	String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
	String num = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
	LogUtil.i("data", "联系人姓名:" + name + ", 电话:" + num);
	cursor.moveToNext();
}

网络存储数据

介绍: 通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息

get请求

public static String loginByGet(String username, String password) {
        String path = http://192.168.0.1:8080/Demo/Login?username= + username + &password= + password;
        try {
            URL url = new URL(path);//将访问的路径转换为url
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();//通过URL获取连接
            conn.setConnectTimeout(5000);//设置连接超时时间
            conn.setRequestMethod(GET);//设置请求方式
            int code = conn.getResponseCode();//返回的状态值
            if (code == 200) {
                InputStream is = conn.getInputStream();
                return StreamTools.streamToString(is);//字节流转换为字符串
            } else {
                return "网络访问失败";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "网络访问失败";
        }
    }

post请求

public static String loginByPost(String username, String password) {
        String path = http://192.168.0.1:8080/Demo/Login;
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod(POST);
            // 设置请求头信息
            conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
            String data = username= + username + &password= + password;
            conn.setRequestProperty(Content-Length, data.length() + );
            conn.setDoOutput(true); //设置可输出流
            OutputStream os = conn.getOutputStream(); //获取输出流
            os.write(data.getBytes()); //将数据写给服务器
            int code = conn.getResponseCode();
            if (code == 200) {
                InputStream is = conn.getInputStream();
                return StreamTools.streamToString(is);
            } else {
                return "网络访问失败";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "网络访问失败";
        }
    }

工具类

public class StreamTools {
	// 将输入流转换成字符串
    public static String streamToString(InputStream is) {
    	ByteArrayOutputStream baos;
        try {
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            LogUtil.i("StreamTools", e.toString());
            return null;
        } finally{
        	baos.close();
            is.close();
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是阿超

现在二师兄的肉比师父的都贵了.

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值