SharedPreferences与Editor

SharedPreferences保存的数据仅仅要是类似于配置信息格式的数据。因此它保存的数据主要是简单的key-value对形式。以下关系图

上图全然能够看出,存的时候用SharedPreferences的内部类Editor,取的时候用SharedPreferences。

SharedPreference是接口无法创建实例,Context提供以下方法创建实例 该实例仅仅能有一个,也就是单例模式。

getSharedPreferences(String name,int mode);

存取样例

 public class MainActivity extends Activity {
SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取SharedPreferences实例 Test是文件名称。不要加后缀,默觉得XML格式
sp = getSharedPreferences("Test", Context.MODE_WORLD_WRITEABLE);
//得到内部类写数据
SharedPreferences.Editor editor = sp.edit();
editor.putString("name", "value");
//不提交则无法获得数据
editor.commit(); }
public void btn(View view){
String string = sp.getString("name", "null");
Toast.makeText(this, string, 1).show();
}
}

存储路径为:data/data/包名/shared_prefs/Test.xml

打开该文件看到

<?xml version="1.0" encoding="utf-8" standalone ="yes" ?>
<map>
<string name="name">value</string>
</map>

存储的放值的时候String相应XML文件中就是string节点。Int的时候相应int节点。

存储时长:卸载软件时包名所在的目录会消失,所以该文件无法相同会消失。

读写其它应用的SharedPreferences

上述是在本身的APP中玩耍,这次看怎样读取其它应用。关键是获得其它应用的程序的Context(代表Android应用的全局信息的接口)又由于包名是Andoird应用的唯一标示,所以调用本APP的Context的方法

createPackageContext("android.example.homework", CONTEXT_IGNORE_SECURITY);

得到其它应用的Context对象而且其它应用SharedPreferences是可读状态(可写不行,必须可读)后就能够“为所欲为”了。

public class MainActivity extends Activity {
SharedPreferences sp; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取SharedPreferences实例
try {
//通过包名得到该应用的Context对象
Context context=createPackageContext("com.example.homework", CONTEXT_IGNORE_SECURITY);
//用其它应用的Context创建SharedPreferences
sp = context.getSharedPreferences("Test", Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void btn(View view) {
String string = sp.getString("name", "null");
Toast.makeText(this, string, 1).show();
}
}

上述的读写并非唯一的,程序猿全然能够利用IO流来直接操作本应用和其它应用的SharedPreferences数据。仅仅是Android将他封装好了,非常简便。

无法存储自己定义类型。主要存储的APP配置信息,比如(username,password等)。

Chche存储

存储空间不够系统会删除Cache存储,但不要依赖系统删除

存:

		File dir = getCacheDir();
File file = new File(dir,"test.txt");
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write("缓冲存储".getBytes()); } catch (Exception e) {
// TODO: handle exception
}

取:

FileInputStream fis = new FileInputStream(file)

以上两种方式均为内部存储,卸载应用时数据都会丢失。

File存储

FIle存储就是Android继续使用Java中的IO流继续读写文件的一种方式

两个核心方法:

openFileInput(String name);

openFIleOutput(String name);

以下是简单读写的样例

public class MainActivity extends Activity {
SharedPreferences sp; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); } public void readed(View view) {
FileInputStream fis = null;
StringBuffer sb=null;
try {
//打开文件输入流 files文件名称。这里系统不给加入后缀,不写无后缀
fis = openFileInput("files");
byte[] buff = new byte[1024];
int len = 0;
sb = new StringBuffer();
while ((len = fis.read(buff)) != -1) {
sb.append(new String(buff, 0, len));
}
//关流
fis.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Toast.makeText(this, sb, 0).show();
} public void writer(View view) {
FileOutputStream fos = null;
try {
// 以追加模式打开文件输出流
fos = openFileOutput("files", MODE_APPEND);
// 将流包装成PrintStream
PrintStream printStream = new PrintStream(fos);
printStream.print("内容啦啦啦啦");
Toast.makeText(this, "写入成功", 0).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fos != null)
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

该文件无后缀,系统默认不加入后缀。存放路径为data/data/包名/file/目录下

该文件依旧存放在包名下,所以卸载时依旧会丢失数据。

SD卡存储

使用File存储和SharedPreferences存储的缺点是容量小,由于在应用程序的数据目录下。所以才有了SD卡存储。使用SD卡存储总共分为三步:

(1)推断应用是否有读写SD卡权限

Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

(2)获得SD卡的文件夹

File dir = Environment.getExternalStorageDirectory();

(3)使用流读写数据

SD卡的权限

	<!-- 加入SD卡的创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 加入SD卡写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

读写SD卡样例

public class MainActivity extends Activity {
private final String FILE_NAME="test.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); }
/**读取数据*/
public void readed(View view) {
BufferedReader bis=null;
//当SD状态装备就绪时
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File dir = Environment.getExternalStorageDirectory();
try {
File file = new File(dir, FILE_NAME);
FileInputStream fis = new FileInputStream(file);
//将fis流包装成BufferedReader
bis= new BufferedReader(new InputStreamReader(fis));
String len = null;
StringBuffer sb = new StringBuffer("");
while((len=bis.readLine())!=null){
sb.append(len);
}
Toast.makeText(this, "读到的数据是:"+sb, 0).show(); } catch (Exception e) {
e.printStackTrace();
}
finally{
if(bis!=null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
else Toast.makeText(this, "SD卡不可用", 0).show(); }
/**写入数据*/
public void writer(View view) {
RandomAccessFile raf = null;
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File dir = Environment.getExternalStorageDirectory();
File file = new File(dir, FILE_NAME);
//用指定文件创建RandomAccessFIle
try {
raf = new RandomAccessFile(file, "rw");
//将文件记录指针移动到最后 防止再次写入覆盖之前的
raf.seek(file.length());
raf.write("来一个字符串玩玩".getBytes());
Toast.makeText(this, "写入成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
}
finally{
if(raf!=null){
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

SQLite存储

SQLite是轻量级的数据库(底层就是一个数据库文件)一旦应用获得了代表指定数据库的SQLiteDatabase对象。接下来就能够通过该对象来管理,操作数据库了。

(1)获取SQLiteDatabase对象。它代表了与数据库的链接。

(2).调用SQLiteDatabase的方法来运行SQL语句。

(3).操作SQL语句的运行结果,比方用SimpleCursorAdapter封装Cursor

(4).关闭SQLiDatabase。回收资源。

经常用法

//创建(假设不存在)或打开数据库
static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory)
//打卡一个已经存在的数据库
static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags)

MainActivity.java

public class MainActivity extends Activity {
private ListView listview;
private SQLiteDatabase db;
private EditText editText;
private String TABLE_NAME="student";
//创建表语句
private String CREATE_TABLE = "create table "+TABLE_NAME+" (_id integer primary key autoincrement,name varchar(20),age integer)";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
editText = (EditText) findViewById(R.id.et);
listview=(ListView) findViewById(R.id.listivew);
//打开或创建数据库(这里须要绝对路径)
db=SQLiteDatabase.openOrCreateDatabase("/mnt/sdcard/my.db3", null);
if(!exits(TABLE_NAME)){
db.execSQL(CREATE_TABLE);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//关闭数据库
if(db!=null&&db.isOpen())
db.close();
}
public void btn(View view){
switch (view.getId()) {
case R.id.btn1://插入
String str = editText.getText().toString();
String sql = "insert into "+TABLE_NAME+" (name) values ('"+str+"') ";
System.out.println(sql);
db.execSQL(sql);
break;
case R.id.btn2://读取
String sql2 = "select * from "+TABLE_NAME+"";
Cursor cursor = db.rawQuery(sql2, null);
inflateListView(cursor);
break;
}
}
public boolean exits(String table){
String sql= "select * from sqlite_master where name="+"'"+table+"'";
System.out.println(sql);
Cursor cursor = db.rawQuery(sql, null);
if(cursor.getCount()!=0){
return true;
}
return false;
}
private void inflateListView(Cursor cursor){
//构建Cursor适配器的同一时候就是对Cursor封装成为Adapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{"name"}, new int[]{android.R.id.text1},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listview.setAdapter(adapter);
}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> <Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btn"
android:text="插入 字符串数据" /> <Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btn"
android:text="取出数据" /> <ListView
android:id="@+id/listivew"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView> </LinearLayout>

效果图:

因为是自己定义的路径,所以卸载软件依旧存在。这样的直接使用SQLiteDatabase的方式使用的极少的。

注意:这里主键的列名必须为_id,由于SimpleCursorAdapter仅仅能识别列名为_id的主键。

android还为我们提供操作数据库的一些便捷方法

insert方法

不管第三个參数是否有数据,运行该方法都会加入一条数据。

        	//table插入的表名
//nullColumnHack强行插入为null列的列名 当values參数为null或不包括随意key-value对时该參数有效
//values代表一行记录的数据
insert(String table, String nullColumnHack, ContentValues values)

实际insert方法底层依旧通过SQL语句来插入的。由于它生成的SQL语句总是形如以下的语句

//ContentValue里的key-value对的数量决定了以下的key-value对。
insert into <表名>(key1,key2...)values(value1,value2....)

假设此时第三个參数为空

insert into <表名>()values()

updata方法

该方法返回的数据库影响的行数

//要更改数据库表名
//更新完毕后的值
//满足whereClaues字句的记录将会被更新
//用于为whereClause字句传入參数
update(String table, ContentValues values, String whereClause, String[] whereArgs)

比如我们想更新person表中的全部主键大于20的人的人名。可调用例如以下方法:

ContentValues values = new ContentValues();
//存放更新之后的人名
values.put("name", "新人名");
db.update("person", values, "_id>? ", new Integer[]{20});

相应SQL语句

updata person set key1=value1,key2=value2...where _id>20

delete方法

返回值更改的行数

//table表名。whereClause删除的条件 。whereArgs给whereClause传入删除的參数
delete(String table, String whereClause, String[] whereArgs)

比如:想删除person表中全部人名以王字开头的记录

db.delete("person","name like?",new String[]{"王%"});

相应SQl语句

delete person where name like '王%'

query方法

//distinct指定是否去除反复记录
//table 运行查询数据的表名
//columns要查询出来的列名
//selection查询条件的字句 相当于select语句wherekeyword后面的部分。
//selectionArgs查询语句匹配的參数
//groupBy用于控制分组,
//having 对分组进行过滤
//orderBy 排序,personid desc降序,age asc升序;
//limit 进行分页  比如:5,10
db.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit, cancellationSignal);
db.query("person", new String[]{"_id,name,age"}, "name like ?", new String[]{"张%"}, null, null, "desc", null);

SQLiteOpenHelper

这样的继承SQLiteOpenHelper方式用的还是比較多的。

它是Android提供的一个管理数据库的工具类,可用于管理数据库的创建的版本号和更新。

经常用法:

synchronized SQLiteDatabase getReadableDatabase();以仅仅读方式打开相应SQLiteDatabase 对象

synchronized SQLiteDatabase getWritableDatabase();以写方式打开相应SQLiteDatabase 对象

abstract void Create(SQLiteDatabase db);第一次创建数据库时回调该方法。

abstract void Upgrade(SQLiteDatabase db,int oldVersion,int newVersion);当数据库版本号更新时回调该方法。

在获得数据库实例时建议使用getReadableDatabase();假设用getWritableDatabase()一旦磁盘满了,打开数据库就会出错,而getReadableDatabase方法先仅仅读方式打开,就算磁盘空间满了,也不会出错,而是继续使用仅仅读方式。

(getReadableDatabase调用时会包括getWritableDatabase)当调用getReadableDatabase()假设数据库不存在调用onCreate(SQLiteDatabase
db);存在之后返回该实例

MyDB.java

public class MyDB extends SQLiteOpenHelper {
//參数1:上下文
//參数2:数据库名字
//參数3:游标工厂(自己定义的时候才用,不须要自己定义null)
//数据库版本
public MyDB(Context context, String name, int version) {
super(context, name, null, version);
// TODO Auto-generated constructor stub
}
public SQLiteDatabase db; final String CREATE_TABLE="create table student(_id integer primary key autoincrement,word varchar(20),detail varchar(20))";
//第一次创建数据库的时候调用。当执行第二次时db==null
@Override
public void onCreate(SQLiteDatabase db) {
this.db=db;
db.execSQL(CREATE_TABLE);
}
//软件升级的时候更新表结构调用,当newVersion>oldVersion时,系统自己主动触发该方法。
//当打开数据库时传入的版本与当前的版本不同一时候会调用该方法
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }

MainActivity.java

public class MainActivity extends Activity {
String a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); MyDB db = new MyDB(this, "mydb.db3", 1);
SQLiteDatabase database = db.getReadableDatabase(); }
}

存储路径data/data/包名/databases/mydb.db3

卸载时文件依旧丢失。

查询的时候会用到Cursor:

经常用法:

isAfterLast()游标的指针是否指向了最后一条数据的后面

moveToNext() 让游标的指针指向下一条数据

moveToFirst() 让游标的指针指向第一条数据

getString(int columnIndex) 获取当前行中指定列的String值。參数列索引

getColumnIndex(StringcolumnName) 依据列名字获取列索引

插入会用到:ContentValus

ContentValus的方法非常easy,键值对而已

改动数据:

//改动   參数1:被改动的表的名字   參数2:改动的成为的值    參数3:更新条件   參数4:更新条件中占位符的值

db.update(DBHelper.TABLE_NAME, values,DBHelper.ENSCORE_NAME+" = ?", new String[]{"hanhan"});

删除数据:

//数据删除  參数1:要删除数据的表的名字   參数2:删除条件    參数3:删除条件中的占位符的值

//返回值---》删除数据的行数

db.delete(DBHelper.TABLE_NAME,DBHelper.ENSCORE_NAME+" = ?", new String[]{"zhangsan"})。

Android 五大存储方式具体解释的更多相关文章

  1. Android数据存储方式--SharedPreferences

    Android数据存储方式有如下四种:SharedPreferences.存储到文件.SQLite数据库.内容提供者(Content provider).存储到网络服务器. 本文主要介绍一下Share ...

  2. Android数据存储方式

    Android提供了5种方式存储数据: 1.使用SharedPreferences存储数据:它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中.只能在同一个 ...

  3. Android的存储方式

    Android常见的四种存储方式: 1. SharePreference 2. File 3. ContentProvider 4. SQLite 第一种: 保存在应用程序私有的文件夹下---- 只有 ...

  4. Android数据存储方式之SharedPreferences

    Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数.使用SharedPreferences保存数据,其背后是用xml文件存放数 ...

  5. android 数据存储方式

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 1,文件 2,内容提供者 3,偏好设置 4,数据库 5,网络存储. 网络存储,就是上传到 ...

  6. Android编程中的5种数据存储方式

    Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...

  7. Android之四大组件、六大布局、五大存储 总结

    Android之四大组件.六大布局.五大存储 一.四大组件:Android四大组件分别为activity.service.content provider.broadcast receiver.   ...

  8. Android之四大组件、六大布局、五大存储

    [-] Android六大界面布局方式 1 LinearLayout线性布局 LinearLayout的常用XML属性及相关方法 LinearLayout子元素支持的常用XML属性及方法 2 Tabl ...

  9. Android——四大组件、六大布局、五大存储

    一.android四大组件 (一)android四大组件详解 Android四大组件分别为activity.service.content provider.broadcast receiver. 1 ...

随机推荐

  1. 字符串格式化输出、while循环、运算符、编码

    1.字符串格式化输出 %占位符: %s => 字符串 %d=>整数型 %%=>转义 普通的% %()不能多,不能少,一一对应 f"{}"大括号里的内容一般都放变量 ...

  2. 洛谷P2770 航空路线问题 最小费用流

    Code: #include<cstdio> #include<iostream> #include<algorithm> #include<vector&g ...

  3. (WC2018模拟十二)【FJOI2016集训Day7T2】点对游戏

    题解: 还好...看懂题目就好做了.(Orzdyh) 首先选择的点是等概率随机的,也就是说每种选择结果的概率都是一样的,所以选择一个点的时候已经选择的点不会有影响,那么就可以直接算出点对个数再求总体的 ...

  4. NOIp2018模拟赛三十七

    奇怪的一场... 前两题都是全场题,C题明显不可做,我题目都没看懂...(STO lhx OTZ) 成绩:100+100+8=208 貌似十几个208的...A题暴力$O(nmc)$能过...暴力容斥 ...

  5. PHP 变量作用域

    以下为 PHP 中的各种变量在底层实现中是如何存储的. 变量: $temp = 'temp'; $temp2 = $temp; // key p *executor_globals.symbol_ta ...

  6. HDU——T 1068 Girls and Boys

    http://acm.hdu.edu.cn/showproblem.php?pid=1068 Time Limit: 20000/10000 MS (Java/Others)    Memory Li ...

  7. 推断扫描后的内容是否是URL

    扫描的明明是Url.竟然当文本给处理了,看来正则没有通过. 扫描二维码后,我參考了QQ的效果.分了三种:网页地址.文件下载地址,文本信息:为了实现这样的效果.我 发现有非常多url非常奇葩.所以就想找 ...

  8. 在使用shape的同一时候,用代码改动shape的颜色属性

    Android里面常常会使用shape来定制一些View的背景 能够改动View的背景颜色.形状等属性 普通情况下.shape都是在xml文件中面写死了.今天遇到一个需求,View的形状是圆角的,可是 ...

  9. [Servlet&amp;JSP] HttpSession会话管理

    我们能够将会话期间必须共享的资料保存在HttpSession中,使之成为属性.假设用户关掉浏览器接受Cookie的功能.HttpSession也能够改用URL重写的方式继续其会话管理功能. HttpS ...

  10. 福利贴——爬取美女图片的Java爬虫小程序代码

    自己做的一个Java爬虫小程序 废话不多说.先上图. 目录命名是用标签缩写,假设大家看得不顺眼能够等完成下载后手动改一下,比方像有强迫症的我一样... 这是挂了一个晚上下载的总大小,只是还有非常多由于 ...