Android提供以下四种存储方式:
SharePreference
SQLite
File
ContentProvider
如果要实现数据共享,正确的方式是使用ContentProvider
SharedPreference
- “用户的偏好设置”通常用来存储程序的一些配置信息。
- 其存储在“data/data/程序包名/shared_prefs目录下。
- 使用键-值的形式来存储数据;我们只需要调用SharedPreferences的getXxx(name), 就可以根据键获得对应的值!
-
SharedPreference本身只能获取数据,存储和修改要通过Editor对象来实现。
代码速记:
存储数据
SharedPreferencessp =context.getSharedPreferences("CITY", MODE_PRIVATE); //获取对象
Editoreditor=sp.edit();
editor.putString("CityName",City.getCity().getCityName());//存储数据
editor.commit();//将数据提交
读取数据
//定义一个读取SP文件的方法
public Map<String, String> read() {
Map<String, String> data =new HashMap<String, String>();
SharedPreferences sp =mContext.getSharedPreferences("mysp", Context.MODE_PRIVATE);
data.put("username", sp.getString("username","")); //获取数据;
data.put("passwd", sp.getString("passwd",""));
return data;
}
SharedPreference工具类:
package com.jay.sharedpreferencedemo3;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Map;
/**
* Created by Jay on 2015/9/2 0002.
*/
public class SPUtils {
/**
* 保存在手机里的SP文件名
*/
public static final String FILE_NAME = "my_sp";
/**
* 保存数据
*/
public static void put(Context context, String key, Object obj) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if (obj instanceof Boolean) {
editor.putBoolean(key, (Boolean) obj);
} else if (obj instanceof Float) {
editor.putFloat(key, (Float) obj);
} else if (obj instanceof Integer) {
editor.putInt(key, (Integer) obj);
} else if (obj instanceof Long) {
editor.putLong(key, (Long) obj);
} else {
editor.putString(key, (String) obj);
}
editor.commit();
}
/**
* 获取指定数据
*/
public static Object get(Context context, String key, Object defaultObj) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
if (defaultObj instanceof Boolean) {
return sp.getBoolean(key, (Boolean) defaultObj);
} else if (defaultObj instanceof Float) {
return sp.getFloat(key, (Float) defaultObj);
} else if (defaultObj instanceof Integer) {
return sp.getInt(key, (Integer) defaultObj);
} else if (defaultObj instanceof Long) {
return sp.getLong(key, (Long) defaultObj);
} else if (defaultObj instanceof String) {
return sp.getString(key, (String) defaultObj);
}
return null;
}
/**
* 删除指定数据
*/
public static void remove(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.remove(key);
editor.commit();
}
/**
* 返回所有键值对
*/
public static Map<String, ?> getAll(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
Map<String, ?> map = sp.getAll();
return map;
}
/**
* 删除所有数据
*/
public static void clear(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
editor.commit();
}
/**
* 检查key对应的数据是否存在
*/
public static boolean contains(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);
return sp.contains(key);
}
}
SQLite
- SQLite是一个轻量级关系型数据库,只有NULL、INTEGER、REAL(浮点数)、TEXT(字符串)和BLOB(大数据)五种类型,不存在BOOLEAN和DATE类型。
- SQLiteOpenHelper:抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法, 我们还可以通过该类的对象获得数据库实例,或者关闭数据库!
- SQLiteDatabase:数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作
- Cursor:游标,有点类似于JDBC里的resultset,结果集!可以简单理解为指向数据库中某 一个记录的指针!
代码速记:
(1).创建数据库
public class MyDBOpenHelper extends SQLiteOpenHelper {
public MyDBOpenHelper(Contextcontext, String name, CursorFactory factory,
int version){super(context, "my.db", null, 1); }
@Override
//数据库第一次创建时被调用
public voidonCreate(SQLiteDatabase db) {
db.execSQL("CREATETABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,nameVARCHAR(20))");
}
//软件版本号发生改变时调用
@Override
public voidonUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTERTABLE person ADD phone VARCHAR(12) NULL");
}
}
(2).插入数据:
dbOpenHelper.getWritableDatabase()
public voidsave(Person p)
{
SQLiteDatabase db =dbOpenHelper.getWritableDatabase();
db.execSQL("<span style="color:#339999;">INSERT</span> INTOperson(name,phone) values(?,?)",new String[]{p.getName(),p.getPhone()});
}
3.删除数据:同上
db.execSQL("DELETEFROM person WHEREpersonid = ?",new String[]{id});
4.修改数据:同上
db.execSQL("UPDATEperson SET name =?,phone = ? WHERE personid = ?",newString[]{p.getName(),p.getPhone(),p.getId()});
5.查询数据:
dbOpenHelper.getReadableDatabase()
public Personfind(Integer id)
{
SQLiteDatabase db =dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM person WHEREpersonid = ?",new String[]{id.toString()});
//存在数据才返回true
if(cursor.moveToFirst())
{
int personid =cursor.getInt(cursor.getColumnIndex("personid"));
String name =cursor.getString(cursor.getColumnIndex("name"));
String phone =cursor.getString(cursor.getColumnIndex("phone"));
return new Person(personid,name,phone);
}
cursor.close();
return null;
}
6.数据分页:
dbOpenHelper.getReadableDatabase()
publicList<Person> getScrollData(int offset,int maxResult)
{
List<Person> person = newArrayList<Person>();
SQLiteDatabase db =dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM person ORDERBY personid ASC LIMIT= ?,?",
newString[]{String.valueOf(offset),String.valueOf(maxResult)});
while(cursor.moveToNext())
{
int personid =cursor.getInt(cursor.getColumnIndex("personid"));
String name =cursor.getString(cursor.getColumnIndex("name"));
String phone =cursor.getString(cursor.getColumnIndex("phone"));
person.add(newPerson(personid,name,phone)) ;
}
cursor.close();
return person;
}
7.查询记录数:
dbOpenHelper.getReadableDatabase()
public longgetCount()
{
SQLiteDatabase db =dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT COUNT (*) FROMperson",null);
cursor.moveToFirst();
long result = cursor.getLong(0);
cursor.close();
return result;
}
PS:除了上面获取条数的方法外还可以使用cursor.getCount()方法获得数据的条数, 但是SQL语句要改改!比如SELECT * FROMperson;
File
文件存储读写
openFileOutput(filename,mode) 往文件写数据
openFileIntput(filename) 读取文件中的信息到程序
getDir(name,mode) 在app的data目录下获取或创建name对应的子目录
getFileDir() 获取app的data目录的file目录的绝对路径
String[]fileList() 返回app的data目录下的全部文件
deleteFile(filename) 删除app的data目录下的指定文件
ContentProvider
ContentProvider相对于其它的方式比较复杂。它能够实现跨应用之间的数据操作。利用ContentResolver对象的delete、update、insert、query等方法去操ContentProvider的对象,让ContentProvider对象的方法去对数据操作。实现方式为:
-
在A程序中定义一个ContentProvider,重载其增删查改等方法;
-
- 在A程序中的AndroidManifest.xml中注册ContentProvider;
- 在B程序中通过ContentResolver和Uri来获取ContentProvider的数据,同样利用Resolver的增删查改方法来获得和处理数据。
在A程序定义一个Provider
public class MyProvider extends ContentProvider {
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean onCreate() {
// 新建个数据库并插入一条数据
SQLiteDatabase db=this.getContext().openOrCreateDatabase("test_db2.db", Context.MODE_PRIVATE, null);
db.execSQL("CREATE TABLE t_user (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL)");
ContentValues values=new ContentValues();
values.put("name", "liangjh2");
db.insert("t_user", "id", values);
db.close();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 获取数据
SQLiteDatabase db=this.getContext().openOrCreateDatabase("test_db2.db", Context.MODE_PRIVATE, null);
Cursor c = db.query("t_user", null, null, null, null, null, null);
db.close();
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
<application ...> ... <provider android:name=".MyProvider" android:authorities="com.example.androidtestdemo" android:exported="true"/> </application>
Context ctx=MainActivity.this;
ContentResolver resolver =ctx.getContentResolver();
Uri uri=Uri.parse("content://com.example.androidtestdemo");
Cursor c = resolver.query(uri, null, null, null, null);
c.moveToFirst();
while(!c.isAfterLast()){
for(int i=0,j=c.getColumnCount();i<j;i++){
Log.v("Android2",""+c.getString(i));
}
c.moveToNext();
}
读取收件箱信息:
private void getMsgs(){ Uri uri = Uri.parse("content://sms/"); ContentResolver resolver = getContentResolver(); //获取的是哪些列的信息 Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null); while(cursor.moveToNext()) { String address = cursor.getString(0); String date = cursor.getString(1); String type = cursor.getString(2); String body = cursor.getString(3); System.out.println("地址:" + address); System.out.println("时间:" + date); System.out.println("类型:" + type); System.out.println("内容:" + body); System.out.println("======================"); } cursor.close(); }
往AndroidManifest.xml加入读取收件箱的权限:
<uses-permission android:name="android.permission.READ_SMS"/>
往收件箱里插入一条信息
private void insertMsg() { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://sms/"); ContentValues conValues = new ContentValues(); conValues.put("address", "123456789"); conValues.put("type", 1); conValues.put("date", System.currentTimeMillis()); conValues.put("body", "no zuo no die why you try!"); resolver.insert(uri, conValues); Log.e("HeHe", "短信插入完毕~"); }