Android提供了4种数据存储技术,分别是SharedPreferences、Files、SQLite数据库和网络存储数据。(有的开发者认为使用ContentProvider也可以算是一种,但我觉得ContentProvider本质上还是用的sqlite,所以未将其纳入其中)

其中最常用的有这三种:SharedPreferences、Files、SQLite数据库。

下面我们分别来认识一下:

1、SharedPreferences

它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。

其存储位置在/data/data/<包名>/shared_prefs目录下。

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。

它主要是通过键值对的方式来存储数据的,获取它的方式有两种:

  1、getSharedPreferences():如果需要多个使用名称来区分的共享文件,则可以使用该方法,其第一个参数就是共享文件的名称。对于使用同一个名称获得的多个SharedPreferences引用,其指向同一个对象。

  2、getPreferences();如果Activity仅需要一个共享文件,则可以使用该方法。因为只有一个文件,它并不需要提供名称。

完成SharedPreferences类中增加值的步骤如下:

  1. 调用SharedPreferences类的edit()方法获得SharedPreferences.Editor对象。
  2. 调用如putBoolean()、putString()等方法附加值
  3. 使用commit()方法提交新值。

SharedPreferences使用时,分两种:

一种是在一个项目中使用,另一个是在两个不同的项目中使用。

下面我们用实例来演示一下,首先是第一种情况(即在一个项目中使用):

首先是布局文件main.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <LinearLayout
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content">
  9. <TextView
  10. android:id="@+id/name_tv"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:text="姓名:"
  14. android:textSize="30sp"/>
  15. <EditText
  16. android:id="@+id/ET_name"
  17. android:layout_width="0dip"
  18. android:layout_height="wrap_content"
  19. android:layout_weight="1"
  20. android:inputType="text"
  21. android:textSize="20sp">
  22. <requestFocus></requestFocus>
  23. </EditText>
  24. </LinearLayout>
  25. <LinearLayout
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content">
  28. <TextView
  29. android:id="@+id/tv_psd"
  30. android:layout_height="wrap_content"
  31. android:layout_width="wrap_content"
  32. android:text="密码:"
  33. android:textSize="30sp"/>
  34. <EditText
  35. android:id="@+id/et_psd"
  36. android:layout_weight="1"
  37. android:layout_height="wrap_content"
  38. android:layout_width="0dip"
  39. android:textSize="20sp"
  40. android:inputType="textPassword"/>
  41. </LinearLayout>
  42. <Button
  43. android:id="@+id/bt_login"
  44. android:layout_height="wrap_content"
  45. android:layout_width="wrap_content"
  46. android:text="登陆"
  47. android:textSize="20sp"/>
  48. </LinearLayout>

read_data.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:id="@+id/tv_rname"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:textSize="30sp"/>
  11. <TextView
  12. android:id="@+id/tv_rpsd"
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:textSize="30sp"/>
  16.  
  17. </LinearLayout>

然后新建两个Activity,分别为ReadActivity和WriteActivity:

  1. public class ReadActivity extends Activity {
  2.  
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. // TODO Auto-generated method stub
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.read_data);
  8. TextView tv_name=(TextView) findViewById(R.id.tv_rname);
  9. TextView tv_psd=(TextView) findViewById(R.id.tv_rpsd);
  10. SharedPreferences sp=getSharedPreferences("test", MODE_PRIVATE);
  11. tv_name.setText(sp.getString("name", "error_name"));
  12. tv_psd.setText(sp.getString("psd", "error_psd"));
  13. }
  14.  
  15. }
  1. public class WriteActivity extends Activity {
  2.  
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. // TODO Auto-generated method stub
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.main);
  8. final EditText et_name=(EditText) findViewById(R.id.ET_name);
  9. final EditText et_psd=(EditText) findViewById(R.id.et_psd);
  10. Button bt_login=(Button) findViewById(R.id.bt_login);
  11. bt_login.setOnClickListener(new OnClickListener() {
  12.  
  13. @Override
  14. public void onClick(View v) {
  15. String name=et_name.getText().toString();
  16. String psd=et_psd.getText().toString();
  17. SharedPreferences sp_login=getSharedPreferences("test", MODE_PRIVATE);
  18. Editor editor=sp_login.edit();
  19. editor.putString("name", name);
  20. editor.putString("psd", psd);
  21. editor.commit();
  22. Intent intent=new Intent();
  23. intent.setClass(WriteActivity.this, ReadActivity.class);
  24. startActivity(intent);
  25.  
  26. }
  27. });
  28. }
  29. }

这里记得把配置文件也要修改一下(注册Activity和修改默认启动Activity):

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.demo_base_sharedpreferences"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6.  
  7. <uses-sdk
  8. android:minSdkVersion="14"
  9. android:targetSdkVersion="19" />
  10.  
  11. <application
  12. android:allowBackup="true"
  13. android:icon="@drawable/ic_launcher"
  14. android:label="@string/app_name"
  15. android:theme="@style/AppTheme" >
  16. <activity
  17. android:name="com.example.demo_base_sharedpreferences.WriteActivity"
  18. android:label="@string/app_name" >
  19. <intent-filter>
  20. <action android:name="android.intent.action.MAIN" />
  21.  
  22. <category android:name="android.intent.category.LAUNCHER" />
  23. </intent-filter>
  24. </activity>
  25. <activity android:name="com.example.demo_base_sharedpreferences.ReadActivity"></activity>
  26. </application>
  27.  
  28. </manifest>

代码完毕,运行程序即可体验SharedPreferences在仅在一个项目中的使用情况。

下面来看看第二种(两个不同项目之间的使用),因为很多代码都是相同的,就直接上代码了

创建第一个项目demo_between_SharedPreferences01

main布局文件代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <LinearLayout
  7. android:layout_height="wrap_content"
  8. android:layout_width="match_parent">
  9. <TextView
  10. android:id="@+id/tv_read"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:text="全局可读:"
  14. android:textSize="20sp"/>
  15. <EditText
  16. android:id="@+id/et_read"
  17. android:layout_width="0dip"
  18. android:layout_height="wrap_content"
  19. android:layout_weight="1"
  20. android:inputType="text"
  21. android:textSize="20sp"/>
  22. </LinearLayout>
  23. <LinearLayout
  24. android:layout_height="wrap_content"
  25. android:layout_width="match_parent">
  26. <TextView
  27. android:id="@+id/tv_write"
  28. android:layout_width="wrap_content"
  29. android:layout_height="wrap_content"
  30. android:text="全局可写:"
  31. android:textSize="20sp"/>
  32. <EditText
  33. android:id="@+id/et_write"
  34. android:layout_width="0dip"
  35. android:layout_height="wrap_content"
  36. android:layout_weight="1"
  37. android:inputType="text"
  38. android:textSize="20sp"/>
  39. </LinearLayout>
  40. <LinearLayout
  41. android:layout_height="wrap_content"
  42. android:layout_width="match_parent">
  43. <TextView
  44. android:id="@+id/tv_read_write"
  45. android:layout_width="wrap_content"
  46. android:layout_height="wrap_content"
  47. android:text="全局可读:"
  48. android:textSize="20sp"/>
  49. <EditText
  50. android:id="@+id/et_read_write"
  51. android:layout_width="0dip"
  52. android:layout_height="wrap_content"
  53. android:layout_weight="1"
  54. android:inputType="text"
  55. android:textSize="20sp"/>
  56. </LinearLayout>
  57. <Button
  58. android:id="@+id/bt_save"
  59. android:layout_width="wrap_content"
  60. android:layout_height="wrap_content"
  61. android:text="保存键值对"
  62. android:textSize="20sp"/>
  63. </LinearLayout>

java文件:

  1. private EditText et_read,et_write,et_read_write;
  2. private SharedPreferences sp_read,sp_write,sp_read_write;
  3.  
  4. @SuppressLint("WorldReadableFiles")
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. et_read=(EditText) findViewById(R.id.et_read);
  10. et_write=(EditText) findViewById(R.id.et_write);
  11. et_read_write=(EditText) findViewById(R.id.et_read_write);
  12. sp_read=getSharedPreferences("read", MODE_WORLD_READABLE);
  13. sp_write=getSharedPreferences("write", MODE_WORLD_WRITEABLE);
  14. sp_read_write=getSharedPreferences("read_write", MODE_WORLD_READABLE+MODE_WORLD_WRITEABLE);
  15. Button bt_save=(Button) findViewById(R.id.bt_save);
  16. bt_save.setOnClickListener( save);
  17. }
  18.  
  19. public OnClickListener save=new OnClickListener() {
  20.  
  21. @Override
  22. public void onClick(View v) {
  23. Editor ed_read=sp_read.edit();
  24. Editor ed_write=sp_write.edit();
  25. Editor ed_read_write=sp_read_write.edit();
  26. ed_read.putString("test", et_read.getText().toString());
  27. ed_write.putString("test", et_write.getText().toString());
  28. ed_read_write.putString("test", et_read_write.getText().toString());
  29. ed_read.commit();
  30. ed_write.commit();
  31. ed_read_write.commit();
  32.  
  33. }
  34. };

创建第二个项目demo_between_SharedPreferences02

main.xml布局文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:id="@+id/read"
  8. android:layout_height="wrap_content"
  9. android:layout_width="wrap_content"
  10. android:textSize="30sp"/>
  11. <TextView
  12. android:id="@+id/write"
  13. android:layout_height="wrap_content"
  14. android:layout_width="wrap_content"
  15. android:textSize="30sp"/>
  16. <TextView
  17. android:id="@+id/read_write"
  18. android:layout_height="wrap_content"
  19. android:layout_width="wrap_content"
  20. android:textSize="30sp"/>
  21.  
  22. </LinearLayout>

java文件

  1. private SharedPreferences sp_read,sp_write,sp_read_write;
  2. private TextView tv_read,tv_write,tv_read_write;
  3.  
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.main);
  8. tv_read=(TextView) findViewById(R.id.read);
  9. tv_write=(TextView) findViewById(R.id.write);
  10. tv_read_write=(TextView) findViewById(R.id.read_write);
  11. Context othercontext=null;
  12. try {
  13. othercontext=createPackageContext("com.example.demo_between_sharepreferences", MODE_PRIVATE);
  14. } catch (NameNotFoundException e) {
  15. // TODO Auto-generated catch block
  16. e.printStackTrace();
  17. }
  18. sp_read=othercontext.getSharedPreferences("read", MODE_WORLD_READABLE);
  19. sp_write=othercontext.getSharedPreferences("write", MODE_WORLD_WRITEABLE);
  20. sp_read_write=othercontext.getSharedPreferences("read_write", MODE_WORLD_READABLE+MODE_WORLD_WRITEABLE);
  21. tv_read.setText("全局可读:"+sp_read.getString("test", "null"));
  22. tv_write.setText("全局可写:"+sp_write.getString("test", "null"));
  23. tv_read_write.setText("全局可读可写:"+sp_read_write.getString("test", "null"));
  24.  
  25. }

然后运行第一个项目,输入信息,点击保存。

运行第二个项目。则界面上显示了用户刚刚在第一个项目中输入并保存的信息。

2、文件Files对象存储

在Android中,文件对象存储主要有两种方式:

  1. java提供的io流体系。(FileOutputStream类的openFileOutput()方法和FileInputStram类提供的openFileInput()方法)默认情况下,使用IO流保存的文件仅对当前应用程序可见。如果用户卸载了该应用程序,则保存数据的文件也会被一起删除。
  2. 使用Environment类的getExternalStorageDirectory()方法对Android中SD卡的操作。

对文件的操作呢,建议大家可以先看看它的相关文档,如我们会使用到的:

http://developer.android.com/intl/zh-cn/reference/java/io/File.html

接下来我们依然用实例来体验一下吧。

第一种使用java提供的io流体系

本实例的布局文件我们使用讲SharedPreferences的第一种情况时使用的布局文件。(注意:在控件的名称上可能会有改动)

然后创建两个Activity:InternalDataWriteActivity和InternalDataReadActivity:

  1. public class InternalDataReadActivity extends Activity {
  2.  
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState); // 调用父类方法
  5. setContentView(R.layout.result);// 使用布局文件
  6. FileInputStream fis = null;
  7. byte[] buffer = null;
  8. try {
  9. fis = openFileInput("login");// 获得文件输入流
  10. buffer = new byte[fis.available()];// 定义保存数据的数组
  11. fis.read(buffer);// 从输入流中读取数据
  12. } catch (FileNotFoundException e) {
  13. e.printStackTrace();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. } finally {
  17. if (fis != null) {
  18. try {
  19. fis.close();// 关闭文件输入流
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25.  
  26. TextView usernameTV = (TextView) findViewById(R.id.username);
  27. TextView passwordTV = (TextView) findViewById(R.id.password);
  28. String data = new String(buffer);// 获得数组中保存的数据
  29. String username = data.split(" ")[0];// 获得username
  30. String password = data.split(" ")[1];// 获得password
  31. usernameTV.setText("用户名:" + username);// 显示用户名
  32. passwordTV.setText("密 码:" + password);// 显示密码
  33. }
  34. }
  1. public class InternalDataWriteActivity extends Activity {
  2. /** Called when the activity is first created. */
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);// 调用父类方法
  6. setContentView(R.layout.main);// 应用布局文件
  7. final EditText usernameET = (EditText) findViewById(R.id.username);// 获得用户名控件
  8. final EditText passwordET = (EditText) findViewById(R.id.password);// 获得密码控件
  9. Button login = (Button) findViewById(R.id.login);// 获得按钮控件
  10. login.setOnClickListener(new View.OnClickListener() {
  11.  
  12. @Override
  13. public void onClick(View v) {
  14. String username = usernameET.getText().toString();// 获得用户名
  15. String password = passwordET.getText().toString();// 获得密码
  16. FileOutputStream fos = null;
  17. try {
  18. fos = openFileOutput("login", MODE_PRIVATE);// 获得文件输出流
  19. fos.write((username + " " + password).getBytes());// 保存用户名和密码
  20. fos.flush();// 清除缓存
  21. } catch (FileNotFoundException e) {
  22. e.printStackTrace();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. if (fos != null) {
  27. try {
  28. fos.close();// 关闭文件输出流
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }
  34. Intent intent = new Intent();// 创建Intent对象
  35. intent.setClass(InternalDataWriteActivity.this, InternalDataReadActivity.class);// 指定跳转到InternalDataReadActivity
  36. startActivity(intent);// 实现跳转
  37. }
  38. });
  39. }
  40. }

最后注意配置文件的修改:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.mingrisoft"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6.  
  7. <uses-sdk android:minSdkVersion="15" />
  8.  
  9. <application
  10. android:icon="@drawable/ic_launcher"
  11. android:label="@string/app_name" >
  12. <activity
  13. android:name="com.mingrisoft.InternalDataWriteActivity"
  14. android:label="@string/app_name" >
  15. <intent-filter>
  16. <action android:name="android.intent.action.MAIN" />
  17.  
  18. <category android:name="android.intent.category.LAUNCHER" />
  19. </intent-filter>
  20. </activity>
  21. <activity android:name="com.mingrisoft.InternalDataReadActivity" />
  22. </application>
  23.  
  24. </manifest>

运行程序,输入数据后,跳转到另一个页面时读取第一个页面的数据。(当然,这种效果也可以使用SharedPreferences)

第二种对安卓的SD卡的操作

修改main.xml布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:background="@drawable/background"
  6. android:orientation="vertical" >
  7.  
  8. <TextView
  9. android:id="@+id/message"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:textColor="@android:color/white"
  13. android:textSize="20dp" />
  14.  
  15. </LinearLayout>

然后创建一个Activity类:

  1. public class FileCreateActivity extends Activity {
  2. /** Called when the activity is first created. */
  3. @Override
  4. public void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);// 调用父类方法
  6. setContentView(R.layout.main);// 应用布局文件
  7. TextView tv = (TextView) findViewById(R.id.message);
  8. File root = Environment.getExternalStorageDirectory();// 获得SD卡根路径
  9. if(root.exists()&&root.canWrite()){
  10. File file = new File(root, "DemoFile.txt");
  11. try {
  12. if (file.createNewFile()) {
  13. tv.setText(file.getName() + "创建成功!");
  14. } else {
  15. if(file.exists()){
  16. file.delete();
  17. tv.setText("已删除同名文件,请重新创建。");
  18. }
  19. else
  20. tv.setText(file.getName() + "创建失败!");
  21.  
  22. }
  23.  
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. }else {
  28. tv.setText("SD卡不存在或者不可写!");
  29. }
  30. }
  31. }

最后在配置文件中添加权限和修改默认Activity:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<activity
android:name="com.mingrisoft.FileCreateActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>
</activity>

此时,即可运行程序。

3、SQLite的数据库存储

Android系统自带有轻量级的数据库—SQLite。它与我们所接触其他数据库大部分都相同,支持大部分的标准SQL语句,分页查询和mysql相同

select * from person(表名) LIMIT 10,20(第10条索引开始,取20条数据)。

另外,它还有个需要注意的地方,那就是不区分数据类型(主键除外)

光说知识点比较空洞,下面我们用一个例子来认识sqlite,在例子中会用注释来解释一些sqlite的知识

不多说直接上代码:

新建一个DBOpenHelper类,并继承SQLiteOpenHelper:

  1. package cn.itcast.sqlite;
  2.  
  3. import android.content.Context;
  4. import android.database.sqlite.SQLiteDatabase;
  5. import android.database.sqlite.SQLiteOpenHelper;
  6.  
  7. public class DBOpenHelper extends SQLiteOpenHelper { // 定义工具类, 继承SQLiteOpenHelper
  8.  
  9. public DBOpenHelper(Context context) { // 创建对象的时候, 需要传入上下文环境
  10. super(context, "itcast.db", null, 4);
  11. /*
  12. * 由于父类没有无参构造函数, 必须显式调用有参的构造函数
  13. * 参数1: 上下文环境, 用来确定数据库文件存储的目录
  14. * 参数2: 数据库文件的名字
  15. * 参数3: 生成游标的工厂, 填null就是使用默认的
  16. * 参数4: 数据库的版本, 从1开始
  17. */
  18. }
  19.  
  20. @Override
  21. public void onCreate(SQLiteDatabase db) {
  22. System.out.println("onCreate");
  23. db.execSQL("CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20))"); // 执行SQL语句, 创建表
  24. }
  25.  
  26. @Override
  27. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  28. System.out.println("onUpgrade");
  29. db.execSQL("ALTER TABLE person ADD balance INTEGER");
  30. }
  31.  
  32. }

创建一个实体类person,接下来的例子中会使用到:

在创建时,get,set方法和一些构造函数可以通过选择菜单栏或点击鼠标右键出现的source选项中选择快速生成。

  1. package cn.itcast.sqlite;
  2.  
  3. public class Person {
  4. private Integer id;
  5. private String name;
  6. private Integer balance;
  7.  
  8. public Person() {
  9. super();
  10. }
  11.  
  12. public Person(String name, Integer balance) {
  13. super();
  14. this.name = name;
  15. this.balance = balance;
  16. }
  17.  
  18. public Person(Integer id, String name, Integer balance) {
  19. super();
  20. this.id = id;
  21. this.name = name;
  22. this.balance = balance;
  23. }
  24.  
  25. public Integer getId() {
  26. return id;
  27. }
  28.  
  29. public void setId(Integer id) {
  30. this.id = id;
  31. }
  32.  
  33. public String getName() {
  34. return name;
  35. }
  36.  
  37. public void setName(String name) {
  38. this.name = name;
  39. }
  40.  
  41. public Integer getBalance() {
  42. return balance;
  43. }
  44.  
  45. public void setBalance(Integer balance) {
  46. this.balance = balance;
  47. }
  48.  
  49. @Override
  50. public String toString() {
  51. return "Person [id=" + id + ", name=" + name + ", balance=" + balance + "]";
  52. }
  53.  
  54. }

下面创建一个操作sql语句的PersonDao类:

该类中,包含了最常用的sql语句,其中的注释的地方希望大家理解意思。

  1. package cn.itcast.sqlite;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import android.content.Context;
  7. import android.database.Cursor;
  8. import android.database.sqlite.SQLiteDatabase;
  9.  
  10. public class PersonDao {
  11. private DBOpenHelper helper;
  12.  
  13. public PersonDao(Context context) {
  14. helper = new DBOpenHelper(context);
  15. }
  16.  
  17. public void insert(Person p) {
  18. SQLiteDatabase db = helper.getWritableDatabase(); // 获取数据库连接(可写的)
  19. db.execSQL("INSERT INTO person(name, balance) VALUES(?, ?)", new Object[] { p.getName(), p.getBalance() }); // 执行SQL语句, 插入
  20. db.close();
  21. }
  22.  
  23. public void delete(int id) {
  24. SQLiteDatabase db = helper.getWritableDatabase();
  25. db.execSQL("DELETE FROM person WHERE id=?", new Object[] { id });
  26. db.close();
  27. }
  28.  
  29. public void update(Person p) {
  30. SQLiteDatabase db = helper.getWritableDatabase();
  31. db.execSQL("UPDATE person SET name=?, balance=? WHERE id=?", new Object[] { p.getName(), p.getBalance(), p.getId() });
  32. db.close();
  33. }
  34.  
  35. public Person query(int id) {
  36. SQLiteDatabase db = helper.getReadableDatabase(); // 获取数据库连接(可读的)
  37. Cursor c = db.rawQuery("SELECT name, balance FROM person WHERE id=?", new String[] { id + "" }); // 执行SQL语句, 查询, 得到游标
  38. Person p = null;
  39. if (c.moveToNext()) { // 判断游标是否包含下一条记录, 如果包含将游标向后移动一位
  40. String name = c.getString(c.getColumnIndex("name")); // 获取"name"字段的索引, 然后根据索引获取数据
  41. int balance = c.getInt(1); // 获取1号索引上的数据
  42. p = new Person(id, name, balance);
  43. }
  44. c.close();
  45. db.close();
  46. return p;
  47. }
  48.  
  49. public List<Person> queryAll() {
  50. SQLiteDatabase db = helper.getReadableDatabase();
  51. Cursor c = db.rawQuery("SELECT id, name, balance FROM person", null);
  52. List<Person> persons = new ArrayList<Person>();
  53. while (c.moveToNext()) {
  54. Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));
  55. persons.add(p);
  56. }
  57. c.close();
  58. db.close();
  59. return persons;
  60. }
  61.  
  62. public int queryCount() {
  63. SQLiteDatabase db = helper.getReadableDatabase();
  64. Cursor c = db.rawQuery("SELECT COUNT(*) FROM person", null);
  65. c.moveToNext();
  66. int count = c.getInt(0);
  67. c.close();
  68. db.close();
  69. return count;
  70. }
  71.  
  72. public List<Person> queryPage(int pageNum, int capacity) {
  73. String offset = (pageNum - 1) * capacity + ""; // 偏移量
  74. String len = capacity + ""; // 个数
  75. SQLiteDatabase db = helper.getReadableDatabase();
  76. Cursor c = db.rawQuery("SELECT id, name, balance FROM person LIMIT ?,?", new String[]{offset , len});
  77. List<Person> persons = new ArrayList<Person>();
  78. while (c.moveToNext()) {
  79. Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));
  80. persons.add(p);
  81. }
  82. c.close();
  83. db.close();
  84. return persons;
  85. }
  86.  
  87. }

最后,我们将用单元测试类来检验我们做得是否正确(注意,不要忘记在配置文件中注册Junit的使用(详见《Android Junit单元测试》一文)):

  1. package cn.itcast.sqlite;
  2.  
  3. import java.util.List;
  4. import java.util.Random;
  5.  
  6. import android.test.AndroidTestCase;
  7.  
  8. public class DBTest extends AndroidTestCase {
  9.  
  10. public void testCreateDatabase() {
  11. DBOpenHelper helper = new DBOpenHelper(getContext());
  12. helper.getWritableDatabase();
  13. /*
  14. * 获取可写的数据连接
  15. * 数据库文件不存在时, 会创建数据库文件, 并且执行onCreate()方法
  16. * 数据库文件存在, 并且版本没有改变时, 不执行任何方法
  17. * 数据库文件存在, 版本提升, 执行onUpgrade()方法
  18. */
  19. }
  20.  
  21. public void testInsert() {
  22. PersonDao dao = new PersonDao(getContext());
  23. for (int i = 1; i <= 100; i++)
  24. dao.insert(new Person("Test" + i, new Random().nextInt(10000)));
  25. }
  26.  
  27. public void testDelete() {
  28. PersonDao dao = new PersonDao(getContext());
  29. dao.delete(1);
  30. }
  31.  
  32. public void testUpdate() {
  33. PersonDao dao = new PersonDao(getContext());
  34. dao.update(new Person(3, "王五", 30000));
  35. }
  36.  
  37. public void testQuery() {
  38. PersonDao dao = new PersonDao(getContext());
  39. System.out.println(dao.query(3));
  40. }
  41.  
  42. public void testQueryAll() {
  43. PersonDao dao = new PersonDao(getContext());
  44. List<Person> persons = dao.queryAll();
  45. for (Person p : persons)
  46. System.out.println(p);
  47. }
  48.  
  49. public void testQueryCount() {
  50. PersonDao dao = new PersonDao(getContext());
  51. System.out.println(dao.queryCount());
  52. }
  53.  
  54. public void testQueryPage() {
  55. PersonDao dao = new PersonDao(getContext());
  56. List<Person> persons = dao.queryPage(3, 20);
  57. for (Person p : persons)
  58. System.out.println(p);
  59. }
  60.  
  61. }

运行程序即可。(该例使用的是System.out输出结果,为方便查看建议add a new logcte filter)

上面是sqlite的最常规和最基本的操作。

下面我们来看看sqlite的一些其他操作:

1、数据库事务的操作。不多说,直接上代码:

在PersonDao类中,添加一个新的方法:(前两个参数代表的是数据库中的ID字段)

  1. public void remit(int from, int to, int amount) {
  2. SQLiteDatabase db = helper.getWritableDatabase();
  3. try {
  4. db.beginTransaction(); // 开始事务
  5. db.execSQL("UPDATE person SET balance=balance-? WHERE id=?", new Object[] { amount, from });
  6. db.execSQL("UPDATE person SET balance=balance+? WHERE id=?", new Object[] { amount, to });
  7. db.setTransactionSuccessful(); // 设置成功点, 在事务结束时, 成功点之前的操作会被提交
  8. /*若此处再接下面的三行代码
  9. db.execSQL("……"); //如果此行的代码出现异常,那么上面的(即前面的)两个execSQL()执行的SQL语句可以正常执行,此行和下面的execSQL()将不会被执行。
  10. db.execSQL("……"); //如果只有此行代码异常,那么最上面的(即前面的)两个execSQL()执行的SQL语句可以正常执行,此行和上面的execSQL()将不会被执行。
  11. db.setTransactionSuccessful();
  12. */
  13. } finally {
  14. db.endTransaction(); // 结束事务, 将成功点之前的操作提交
  15. db.close();
  16. }
  17. }

在DBtest单元测试类中,测试刚刚添加的有关事务的方法:

  1. public void testRemit() {
  2. PersonDao dao = new PersonDao(getContext());
  3. dao.remit(3, 2, 1000);
  4. }

2、另一种数据操作(增删查改)的方式

这种方式呢,不需要写SQL语句。但是,它的实质是转换成sql语句再执行。在某些情况下呢,对数据的操作会更加方便。

下面,我们就将PersonDao类用新的数据操作的方式来实现一下,大家可以对比一下与之前的PersonDao类的区别,其实真正关键的、不同的代码就那么几句,大部分还是相同的。

  1. package cn.itcast.sqlite;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import android.content.ContentValues;
  7. import android.content.Context;
  8. import android.database.Cursor;
  9. import android.database.sqlite.SQLiteDatabase;
  10.  
  11. public class PersonDao {
  12. private DBOpenHelper helper;
  13.  
  14. public PersonDao(Context context) {
  15. helper = new DBOpenHelper(context);
  16. }
  17.  
  18. public void insert(Person p) {
  19. SQLiteDatabase db = helper.getWritableDatabase(); // 获取数据库连接(可写的)
  20. ContentValues values = new ContentValues(); // 类似于Map的容器, 键是String, 用来存放列名, 值是Object, 用来存要插入的数据
  21. values.put("name", p.getName()); // 某些情况下, 程序会接收一个ContentValues参数, 这时用这种方式存储比较方便
  22. values.put("balance", p.getBalance());
  23. long id = db.insert("person", null, values); // 第二个参数随便写表中的一个列名即可, 用来在想插入一条除了主键全部为空的记录时使用
  24. System.out.println("插入的记录的id是: " + id);
  25. db.close();
  26. }
  27.  
  28. public void delete(int id) {
  29. SQLiteDatabase db = helper.getWritableDatabase();
  30. int rows = db.delete("person", "id=?", new String[] { id + "" });
  31. System.out.println("删除了" + rows + "行");
  32. db.close();
  33. }
  34.  
  35. public void update(Person p) {
  36. SQLiteDatabase db = helper.getWritableDatabase();
  37. ContentValues values = new ContentValues();
  38. values.put("name", p.getName());
  39. values.put("balance", p.getBalance());
  40. int rows = db.update("person", values, "id=?", new String[] { p.getId() + "" });
  41. System.out.println("更新了" + rows + "行");
  42. db.close();
  43. }
  44.  
  45. public Person query(int id) {
  46. SQLiteDatabase db = helper.getReadableDatabase(); // 获取数据库连接(可读的)
  47. Cursor c = db.query("person", new String[] { "name", "balance" }, "id=?", new String[] { id + "" }, null, null, null);
  48. Person p = null;
  49. if (c.moveToNext()) { // 判断游标是否包含下一条记录, 如果包含将游标向后移动一位
  50. String name = c.getString(c.getColumnIndex("name")); // 获取"name"字段的索引, 然后根据索引获取数据
  51. int balance = c.getInt(1); // 获取1号索引上的数据
  52. p = new Person(id, name, balance);
  53. }
  54. c.close();
  55. db.close();
  56. return p;
  57. }
  58.  
  59. public List<Person> queryAll() {
  60. SQLiteDatabase db = helper.getReadableDatabase();
  61. Cursor c = db.query("person", null, null, null, null, null, "id DESC");
  62. List<Person> persons = new ArrayList<Person>();
  63. while (c.moveToNext()) {
  64. Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));
  65. persons.add(p);
  66. }
  67. c.close();
  68. db.close();
  69. return persons;
  70. }
  71.  
  72. public int queryCount() {
  73. SQLiteDatabase db = helper.getReadableDatabase();
  74. Cursor c = db.query("person", new String[]{ "COUNT(*)" }, null, null, null, null, null);
  75. c.moveToNext();
  76. int count = c.getInt(0);
  77. c.close();
  78. db.close();
  79. return count;
  80. }
  81.  
  82. public List<Person> queryPage(int pageNum, int capacity) {
  83. String offset = (pageNum - 1) * capacity + ""; // 偏移量
  84. String len = capacity + ""; // 个数
  85. SQLiteDatabase db = helper.getReadableDatabase();
  86. Cursor c = db.query("person", null, null, null, null, null, null, offset + "," + len);
  87. List<Person> persons = new ArrayList<Person>();
  88. while (c.moveToNext()) {
  89. Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));
  90. persons.add(p);
  91. }
  92. c.close();
  93. db.close();
  94. return persons;
  95. }
  96.  
  97. public void remit(int from, int to, int amount) {
  98. SQLiteDatabase db = helper.getWritableDatabase();
  99. try {
  100. db.beginTransaction(); // 开始事务
  101. db.execSQL("UPDATE person SET balance=balance-? WHERE id=?", new Object[] { amount, from });
  102. db.execSQL("UPDATE person SET balance=balance+? WHERE id=?", new Object[] { amount, to });
  103. db.setTransactionSuccessful(); // 设置成功点, 在事务结束时, 成功点之前的操作会被提交
  104. } finally {
  105. db.endTransaction(); // 结束事务, 将成功点之前的操作提交
  106. db.close();
  107. }
  108. }
  109.  
  110. }

Android数据存储技术的更多相关文章

  1. 详解Android数据存储技术

    前言 学习Android相关知识,数据存储是其中的重点之一,如果不了解数据,那么让你跟一款没有数据的应用玩,你能玩多久呢?答案是这和没有手机几乎是差不多的.我们聊QQ,聊微信,看新闻,刷朋友圈等都是看 ...

  2. Android实现数据存储技术

    转载:Android实现数据存储技术 本文介绍Android中的5种数据存储方式. 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用Shar ...

  3. Android数据存储五种方式总结

    本文介绍Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据     2 文件存储数据       3 SQLite数据库存储数据 4 使用Cont ...

  4. Android - 数据存储 -存储文件

    Android使用的文件系统和其他平台的基本磁盘的文件系统很相似.这里将要介绍如何使用File API在Android文件系统中读写文件. File对象适合按顺序读写大量的数据.例如,适合图片文件或者 ...

  5. 安卓开发_数据存储技术_sqlite

    一.SQLite SQLite第一个Alpha版本诞生于2000年5月,它是一款轻量级数据库,它的设计目标是嵌入式的,占用资源非常的低,只需要几百K的内存就够了.SQLite已经被多种软件和产品使用 ...

  6. 安卓开发_数据存储技术_SharedPreferences类

    SharedPreferences类 供开发人员保存和获取基本数据类型的键值对. 该类主要用于基本类型,例如:booleans,ints,longs,strings.在应用程序结束后,数据仍旧会保存. ...

  7. Android数据存储:Shared Preferences

    Android数据存储之SharedPreferences 在Android系统中提供了多种存储技术.通过这些存储技术可以将数据存储在各种存储介质上, Android 为数据存储提供了如下几种方式:1 ...

  8. Android 数据存储04之Content Provider

    Content Provider 版本 修改内容 日期 修改人 V1.0 原始版本 2013/2/25 skywang 1 URI 通用资源标志符(Universal Resource Identif ...

  9. Android 数据存储03之SQLite

    SQLite数据存储 Android 集成了 SQLite 数据库.它存储在 /data/data/< 项目文件夹 >/databases/ 下.Android 开发中使用 SQLite ...

随机推荐

  1. 【原】 Spark中Worker源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Worker源码分析(一)http://www.cnblogs.com/yourarebest/p/5300202.html 4.receive方法, r ...

  2. git 实用命令

    git 覆盖本地修改 ,git 放弃本地修改,强制更新 git fetch --all git reset --hard origin/master git fetch 只是下载远程的库的内容,不做任 ...

  3. 华为2015 简单 字典输入法 java

    题目摘自http://blog.csdn.net/dongyi91/article/details/38639915 写了2个小时,水平太菜了 入法的编码原理为:根据已有编码表,当输入拼音和数字后输出 ...

  4. linux内核申请内存函数

    kmap函数:    把某块高端内存映射到页表,然后返回给用户一个填好vitual字段的page结构    建立永久地址映射,不是简单的返回virtual字段的pageioremap:    驱动程序 ...

  5. 微软2016校园招聘4月在线笔试 ABC

    题目链接:http://hihocoder.com/contest/mstest2016april1/problems 第一题:输入N,P,W,H,代表有N段文字,每段有ai个字,每行有⌊W/S⌋个字 ...

  6. requirejs 打包参数

    https://github.com/requirejs/r.js/blob/master/build/example.build.js

  7. Python 学习入门(28)—— 服务器实例

    在新的Python 3.x中,BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer整合到http.server包,SocketServer改名为sockets ...

  8. URL与资源

    资源推荐 1.HTTP权威指南. <HTTP权威指南>由古尔利所著,<HTTP权威指南>详细解释了HTTP协议,包括HTTP是如何工作的,如何用HTTP来开发基于Web的应用程 ...

  9. 微软的.NET示例代码放在Github上了

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:微软的.NET示例代码放在Github上了.

  10. 【面试虐菜】—— MongoDB知识整理

    为什么我们要使用MongoDB? 特点: 高性能.易部署.易使用,存储数据非常方便.主要功能特性有: 面向集合存储,易存储对象类型的数据. 模式自由. 支持动态查询. 支持完全索引,包含内部对象. 支 ...