游子的博客
慈母手中线,游子身上衣, 临行密密缝,意恐迟迟归, 谁言寸草心,报得三春晖。 数据读取中,请稍候......
posts - 337,  comments - 546,  trackbacks - 0

/*

 *  Android开发之数据保存技术(一)

 *  北京Android俱乐部群:167839253

 *  Created on: 2011-8-17

 *  Author: blueeagle

 *  Email: liujiaxiang@gmail.com

 */

 

       Android通过SQLite库提供了完善的关系数据库功能,而没有强加任何额外的限制。通过使用SQLite,可以为每一个应用程序创建独立的关系数据库。

       所有的Android数据库都存储在/data/data/<package_name>/databases文件夹下。默认条件下,所有的数据库都是私有的,并且只能被创建它们的应用程序访问。要跨应用程序共享数据库,可以使用内容提供器。

       SQLite是一个关系数据管理系统。它被普遍认为是:开源,兼容标准,轻量级,Single-tier。

可以用一个例子来演示SQLite。该例子将记录存储在一个数据库中,然后显示出来。

       新建一个HelloSQLite的程序。

       需要在某个地方放置该数据库中描述的一些常量,所以要创建一个Constants接口。

代码如下:

  1. package com.blueeagle;  
  2.   
  3.    
  4.   
  5. import android.provider.BaseColumns;  
  6.   
  7. public interface Constants extends BaseColumns {  
  8.   
  9.     /** Called when the activity is first created. */  
  10.   
  11.     public static final String TABLE_NAME = "HelloSQLite";  
  12.   
  13.     public static final String TIME = "time";  
  14.   
  15.     public static final String TITLE = "title";  
  16.   
  17.     }  


       每个事件都将作为HeloSQLite表中的一行进行存储。每行都包含一个_id、time和title列。_id是主键,在扩展的BaseColums接口中声明。time和title分别作为时间和事件标记。

 

使用SQliteOpenHelper。接下来,创建一个名为SQLiteData的帮助器来表示数据库本身。这个类扩展自Android的SQLiteOpenHelper类,它负责管理数据库的创建和版本。需要做的就是提供一个构造方法并且覆写两个方法。

       代码如下:


  1.   
  2. package com.blueeagle;  
  3.   
  4.    
  5.   
  6. import android.content.Context;  
  7.   
  8. import android.database.sqlite.SQLiteDatabase;  
  9.   
  10. import android.database.sqlite.SQLiteDatabase.CursorFactory;  
  11.   
  12. import android.database.sqlite.SQLiteOpenHelper;  
  13.   
  14. import static com.blueeagle.Constants.TABLE_NAME;  
  15.   
  16. import static com.blueeagle.Constants.TIME;  
  17.   
  18. import static com.blueeagle.Constants.TITLE;  
  19.   
  20. import static android.provider.BaseColumns._ID;  
  21.   
  22.    
  23.   
  24. public class MySQLite extends SQLiteOpenHelper {  
  25.   
  26.       
  27.   
  28.     private static final String DATABASE_NAME = "MySQLite.db";  
  29.   
  30.     private static final int DATABASE_VERSION = 1;  
  31.   
  32.       
  33.   
  34.     public MySQLite(Context context, String name, CursorFactory factory,  
  35.   
  36.            int version) {  
  37.   
  38.        super(context, DATABASE_NAME, factory, DATABASE_VERSION);  
  39.   
  40.        // TODO Auto-generated constructor stub  
  41.   
  42.     }  
  43.   
  44.    
  45.   
  46.     @Override  
  47.   
  48.     public void onCreate(SQLiteDatabase db) {  
  49.   
  50.        // TODO Auto-generated method stub  
  51.   
  52.        db.execSQL("CREATE TABLE "+ TABLE_NAME+"("+_ID+"INTEGER PRIMARY KEY AUTOINCREMENT,"+TIME+"INTEGER,"+TITLE+"TEXT NOT NULL);");  
  53.   
  54.     }  
  55.   
  56.    
  57.   
  58.     @Override  
  59.   
  60.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  61.   
  62.        // TODO Auto-generated method stub  
  63.   
  64.        db.execSQL("DROP TABLE IF EXISTS" + TABLE_NAME);  
  65.   
  66.        onCreate(db);  
  67.   
  68.          
  69.   
  70.     }  
  71.   
  72. }  


首次访问数据库时,SQLiteOpenHelper将注意到该数据库不存在,并调用onCreate()方法来创建它。

定义Activity主程序。

在HelloSQLite程序中做的第一次尝试是使用本地的SQLite数据库来存储事件,并将这些事件显示为TextView中的一个字符串。

布局xml文件如下:

  1. main.xml  
  2.   
  3. <?xml version="1.0" encoding="utf-8"?>  
  4.   
  5. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
  6.   
  7.     android:layout_width="fill_parent"  
  8.   
  9.     android:layout_height="fill_parent"  
  10.   
  11.     >  
  12.   
  13. <TextView    
  14.   
  15.     android:id="@+id/myText"  
  16.   
  17.     android:layout_width="fill_parent"   
  18.   
  19.     android:layout_height="wrap_content"   
  20.   
  21.     />  
  22.   
  23. </ScrollView>  


 

这段代码使用一个ScrollView,以防太多的时间沾满了屏幕。

对于HelloSQLite.java的实现如下所示:相关代码有注释说明。

  1. package com.blueeagle;  
  2.   
  3.   
  4. import android.app.Activity;  
  5.   
  6. import android.content.ContentValues;  
  7.   
  8. import android.database.Cursor;  
  9.   
  10. import android.database.sqlite.SQLiteDatabase;  
  11.   
  12. import android.os.Bundle;  
  13.   
  14. import android.widget.TextView;  
  15.   
  16. import static com.blueeagle.Constants.TABLE_NAME;  
  17.   
  18. import static com.blueeagle.Constants.TIME;  
  19.   
  20. import static com.blueeagle.Constants.TITLE;  
  21.   
  22. import static android.provider.BaseColumns._ID;  
  23.   
  24.    
  25.   
  26. public class HelloSQLite extends Activity {  
  27.   
  28.     /** Called when the activity is first created. */  
  29.   
  30.     private MySQLite mySqlite;  
  31.   
  32.     private static String[] FROM={_ID,TIME,TITLE};  
  33.   
  34.     private static String ORDER_BY = TIME+" DESC";  
  35.   
  36.     @Override  
  37.   
  38.     public void onCreate(Bundle savedInstanceState) {  
  39.   
  40.         super.onCreate(savedInstanceState);  
  41.   
  42.         setContentView(R.layout.main);  
  43.   
  44.           
  45.   
  46.         mySqlite = new MySQLite(this);  
  47.   
  48.         try{  
  49.   
  50.         addItem("Hello,Android!");  
  51.   
  52.         Cursor cursor = getItems();  
  53.   
  54.         showItems(cursor);  
  55.   
  56.         }  
  57.   
  58.         finally{  
  59.   
  60.         mySqlite.close();  
  61.   
  62.         }  
  63.   
  64.     }  
  65.   
  66.     //显示查询结果  
  67.   
  68.     private void showItems(Cursor cursor) {  
  69.   
  70.        // TODO Auto-generated method stub  
  71.   
  72.        StringBuilder builder = new StringBuilder("Saved items:\n");  
  73.   
  74.        while(cursor.moveToNext()){  
  75.   
  76.            long id = cursor.getLong(0);  
  77.   
  78.            long time = cursor.getLong(1);  
  79.   
  80.            String title = cursor.getColumnName(2);  
  81.   
  82.            builder.append(id).append(": ");  
  83.   
  84.            builder.append(time).append(": ");  
  85.   
  86.            builder.append(title).append("\n");  
  87.   
  88.        }  
  89.   
  90.        TextView myTextView = (TextView)findViewById(R.id.myText);  
  91.   
  92.        myTextView.setText(builder);  
  93.   
  94.     }  
  95.   
  96.     //此函数接受一个Cursor作为输入并格式化,以便用户能够理解输出的内容  
  97.   
  98.     //查询条目方法  
  99.   
  100.     private Cursor getItems() {  
  101.   
  102.        // TODO Auto-generated method stub  
  103.   
  104.        SQLiteDatabase db = mySqlite.getReadableDatabase();  
  105.   
  106.        Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, ORDER_BY);  
  107.   
  108.        startManagingCursor(cursor);  
  109.   
  110.        return cursor;  
  111.   
  112.     }  
  113.   
  114.     //因为查询不用修改数据库,因此利用只读句柄,然后调用查询的query方法来执行SQL语句,FROM是  
  115.   
  116.     //想要使用的列构成的数组,ORDER_BY告诉SQLite按照从新到旧的顺序返回查询结果。  
  117.   
  118.     //添加条目方法  
  119.   
  120.     private void addItem(String string) {  
  121.   
  122.        // TODO Auto-generated method stub  
  123.   
  124.        SQLiteDatabase db = mySqlite.getWritableDatabase();  
  125.   
  126.        ContentValues values = new ContentValues();  
  127.   
  128.        values.put(TIME, System.currentTimeMillis());  
  129.   
  130.        values.put(TITLE, string);  
  131.   
  132.        db.insert(TABLE_NAME, null, values);  
  133.   
  134.     }  
  135.   
  136.     //因为要修改数据库,所以调用getWritableDatabase()方法来获取数据库的一个写句柄,当然也可以获取  
  137.   
  138.     //到读句柄。  
  139.   
  140. }  


完成上述文件-》运行,即可看到结果显示出来。这样就完成了第一个Android数据库程序。

当然,这里面需要注意的问题:

1.       新建数据库的问题

新建数据库的时候,会遇到我们用:

db.execSQL("CREATE TABLE "+ TABLE_NAME+"("+_ID+"INTEGER PRIMARY KEY AUTOINCREMENT,"+TIME+"INTEGER,"+TITLE+"TEXT NOT NULL);");

这样一条语句。有时候SQL语句书写错误,比如少一个空格就会引起程序异常退出。这个时候建议在db.execSQL()函数中填写一个字符串变量,然后把自己写的SQL语句赋给字符串变量,在做赋值操作的时候,先打印出来看看,是不是少空格,多+号什么的小错误。

2.       版本号的问题

关于构造函数中的版本号,是有明确的说明的。

    public MySQLite(Context context, String name, CursorFactory factory,

           int version) {

       super(context, DATABASE_NAME, factory, DATABASE_VERSION);

这个版本号version当你有新版本的时候,则做更新操作,新版本的版本号将要比老版本高,如果此时修改版本号,不是向高修改,而是向低修改的话,程序就会发生异常了。

 

3.       数据库文件的问题

对于onCreate()方法,在程序运行的时候,只运行一次,运行的这一次就是去创建数据库。将数据库的文件存储在SD卡中。路径是data/data/包名/databases里。可以在Eclipse里通过DDMS里的File Explorer来查看。当数据库文件存在了以后,则不会再次运行。

 

完成了上述例子,就算完成了一个数据库的应用。但是如果列表中有数千个或者上百万个事件。程序将运行的非常慢。甚至于耗尽内存。解决办法就是数据绑定。

有了数据绑定,只需要几行代码,就可以将数据连接到视图,从而实现需求。为了演示,我们修改上面的实例。

将主程序HelloSQLite.java继承ListActivity而不是Activity。

将代码修改为如下所示:

 

  1. package com.blueeagle;  

  2.   
  3. import android.app.ListActivity;  
  4.   
  5. import android.content.ContentValues;  
  6.   
  7. import android.database.Cursor;  
  8.   
  9. import android.database.sqlite.SQLiteDatabase;  
  10.   
  11. import android.os.Bundle;  
  12.   
  13. import android.widget.SimpleCursorAdapter;  
  14.   
  15. import static com.blueeagle.Constants.TABLE_NAME;  
  16.   
  17. import static com.blueeagle.Constants.TIME;  
  18.   
  19. import static com.blueeagle.Constants.TITLE;  
  20.   
  21. import static android.provider.BaseColumns._ID;  
  22.   
  23.    
  24.   
  25. public class HelloSQLite extends ListActivity {  
  26.   
  27.     /** Called when the activity is first created. */  
  28.   
  29.     private MySQLite mySqlite;  
  30.   
  31.     private static String[] FROM={_ID,TIME,TITLE};  
  32.   
  33.     private static String ORDER_BY = TIME+" DESC";  
  34.   
  35.     //@Override  
  36.   
  37.     public void onCreate(Bundle savedInstanceState) {  
  38.   
  39.         super.onCreate(savedInstanceState);  
  40.   
  41.         setContentView(R.layout.main);  
  42.   
  43.           
  44.   
  45.         mySqlite = new MySQLite(this);  
  46.   
  47.         try{  
  48.   
  49.         addItem("Hello,Android!");  
  50.   
  51.         Cursor cursor = getItems();  
  52.   
  53.         showItems(cursor);  
  54.   
  55.         }  
  56.   
  57.         finally{  
  58.   
  59.         mySqlite.close();  
  60.   
  61.         }  
  62.   
  63.     }  
  64.   
  65.     private static int[] TO = {R.id.rowid,R.id.time,R.id.title};  
  66.   
  67.     private void showItems(Cursor cursor) {  
  68.   
  69.     SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.item,cursor,FROM,TO);  
  70.   
  71.     //这里有必要说明一下SimpleCursorAdapter构造函数的5个参数。1.对应于当前Activity的引用,2.一个资源,它定义一个列表条目的视图,  
  72.   
  73.     //3.数据集光标,4.一组列名称,数据来源于这些列。5.视图列表,这是数据的目的地。  
  74.   
  75.     setListAdapter(adapter);  
  76.   
  77.       
  78.   
  79.     }  
  80.   
  81.     private Cursor getItems() {  
  82.   
  83.        SQLiteDatabase db = mySqlite.getReadableDatabase();  
  84.   
  85.        Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, ORDER_BY);  
  86.   
  87.        startManagingCursor(cursor);  
  88.   
  89.        return cursor;  
  90.   
  91.     }  
  92.   
  93.     private void addItem(String string) {  
  94.   
  95.        // TODO Auto-generated method stub  
  96.   
  97.        SQLiteDatabase db = mySqlite.getWritableDatabase();  
  98.   
  99.        ContentValues values = new ContentValues();  
  100.   
  101.        values.put(TIME, System.currentTimeMillis());  
  102.   
  103.        values.put(TITLE, string);  
  104.   
  105.        db.insert(TABLE_NAME, null, values);  
  106.   
  107.     }  
  108.   
  109. }  


将main.xml修改成如下形式:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   
  5.     android:layout_width="fill_parent"  
  6.   
  7.     android:layout_height="fill_parent"  
  8.   
  9.     >  
  10.   
  11. <ListView  
  12.   
  13. android:id="@android:id/list"  
  14.   
  15. android:layout_height="wrap_content"  
  16.   
  17. android:layout_width="wrap_content">  
  18.   
  19. </ListView>  
  20.   
  21. <TextView  
  22.   
  23. android:id="@android:id/empty"  
  24.   
  25. android:layout_height="wrap_content"  
  26.   
  27. android:layout_width="wrap_content"  
  28.   
  29. android:text="empty!">  
  30.   
  31. </TextView>  
  32.   
  33. </LinearLayout>  


 

增加item.xml为如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   
  5.     android:orientation="horizontal"  
  6.   
  7.     android:layout_width="fill_parent"  
  8.   
  9.     android:layout_height="fill_parent"  
  10.   
  11.     android:padding="10sp"  
  12.   
  13.     >  
  14.   
  15. <TextView  
  16.   
  17. android:id="@+id/rowid"  
  18.   
  19. android:layout_height="wrap_content"  
  20.   
  21. android:layout_width="wrap_content">  
  22.   
  23. </TextView>  
  24.   
  25. <TextView  
  26.   
  27. android:id="@+id/rowidcolon"  
  28.   
  29. android:layout_height="wrap_content"  
  30.   
  31. android:layout_width="wrap_content"  
  32.   
  33. android:text=":"  
  34.   
  35. android:layout_toRightOf="@id/rowid">  
  36.   
  37. </TextView>  
  38.   
  39. <TextView  
  40.   
  41. android:id="@+id/time"  
  42.   
  43. android:layout_height="wrap_content"  
  44.   
  45. android:layout_width="wrap_content"  
  46.   
  47. android:layout_toRightOf="@id/rowidcolon">  
  48.   
  49. </TextView>  
  50.   
  51. <TextView  
  52.   
  53. android:id="@+id/timecolon"  
  54.   
  55. android:layout_height="wrap_content"  
  56.   
  57. android:layout_width="wrap_content"  
  58.   
  59. android:text=":"  
  60.   
  61. android:layout_toRightOf="@id/time">  
  62.   
  63. </TextView>  
  64.   
  65. <TextView  
  66.   
  67. android:id="@+id/title"  
  68.   
  69. android:layout_height="fill_parent"  
  70.   
  71. android:layout_width="wrap_content"  
  72.   
  73. android:textStyle="italic"  
  74.   
  75. android:ellipsize="end"  
  76.   
  77. android:singleLine="true"  
  78.   
  79. android:layout_toRightOf="@id/timecolon">  
  80.   
  81. </TextView>  
  82.   
  83. </RelativeLayout>  


运行结果如图所示。

 

当然,这只是一个DEMO,用来展示如何使用SQLite,这个DEMO存在一些问题。其他应用程序都不能向事件数据库添加内容,甚至于无法看这些事件。那么针对这一点,引出了Android里的内容提供器,即ContentProvider。

posted on 2013-02-20 10:38 游子 阅读(2811) 评论(0)  编辑 收藏 引用 所属分类: 软件
只有注册用户登录后才能发表评论。

欢迎大家扔鸡蛋!送鲜花!

博客可以收入过千吗?

<2013年2月>
日一二三四五六2728293031123456789101112131415161718
19202122232425262728123456789

常用链接

留言簿(8)

随笔分类(314)

随笔档案(337)

文章分类(7)

文章档案(10)

相册

收藏夹(1)

其它

友情链接

数字电视

生活、旅游

自己的链接

计算机

搜索

  •  

积分与排名

  • 积分 - 403154
  • 排名 - 9

最新评论

阅读排行榜

评论排行榜