`
朱嘉华
  • 浏览: 233158 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

android 完整地操作数据库--日记本实例

阅读更多

在上一个例子中,我们对Android系统自带的SQLite数据库进行了初步的学习,了解了一些增、删、改、查的基本工作。在这一节的例子当中,我们做了一个非常简便的日记本程序,虽然没有完善,但是已经是基本可以使用了。在例子当中,我们不但要对数据库进行增、删、改、查的操作,而且还要把数据库当中的数据显示在一个ListView当中,通过对ListView的操作,实现对数据的增、删、改、查操作。

通过这个例子我们可以学到以下操作:

如何对DatabaseHelper和SQLiteDatabase封装,以便让我们访问数据库更加方便和安全;

如何利用ContentValues类来代替原始的SQL语句进行数据库的操作;

如何使用SimpleCursorAdapter类和ListView配合进行ListView的显示。

日记本具体实现步骤如下所述。

1.第一步

在Eclipse中打开ex08_2_SQLite 项目,具体操作步骤如下。

新建一个项目。单击File→New→Android Project项。

在新建项目的对话框中,选择Create project from existing source项。

单击浏览,找到ex08_2_SQLite项目,然后单击确定。

程序的目录结构如图8-16所示。

2.第二步

我们首先运行一下建立的程序,将会出现如图8-17所示。

 
(点击查看大图)图8-16  程序的目录结构
 
(点击查看大图)图8-17  没有任何数据的程序主界面

程序的主Activity是ActivityMain,它是一个ListActivity,和它关联的布局文件是diary_list.xml。关于ListActivity的介绍。请参阅第7章关于ListView的介绍。

3.第三步

在继续操作前,让我们重点关注一下DiaryDbAdapter类,这个类封装了DatabaseHelper和SQLiteDatabase类,使得我们对数据库的操作更加安全和方便。

在DiaryDbAdapter的类变量里,主要定义了以下几个变量:

数据库、数据表、数据表中列的名字;

DatabaseHelper 和SQLiteDatabase的实例;

Context 实例。

DatabaseHelper 类的定义和上一个例子一样,只不过这个例子里边,我们在onUpgrade增加了升级的代码,具体如下所示:

  1. private static class DatabaseHelper extends SQLiteOpenHelper {  
  2.  
  3.          DatabaseHelper(Context context) {  
  4.              super(context, DATABASE_NAME, null, DATABASE_VERSION);  
  5.          }  
  6.  
  7.          @Override 
  8.          public void onCreate(SQLiteDatabase db) {  
  9. //生成数据库  
  10.             db.execSQL(DATABASE_CREATE);  
  11.  
  12.          @Override 
  13.          public void onUpgrade(SQLiteDatabase db,  int oldVersion, int newVersion) {  
  14.              db.execSQL("DROP TABLE IF EXISTS diary");  
  15.              onCreate(db);  
  16.          }  
  17.     } 

代码解释:

在DiaryDbAdapter类里,向外界提供了以下一些方法。

open(),调用这个方法后,如果数据库还没有建立,那么会建立数据库,如果数据库已经建立了,那么会返回可写的数据库实例。

close(),调用此方法,DatabaseHelper 会关闭对数据库的访问。

createDiary(String title, String body)通过一个title和body字段在数据库当中创建一条新的纪录。

deleteDiary(long rowId)通过记录的id,删除数据库中的那条记录。

getAllNotes()得到diary表中所有的记录,并且以一个Cursor的形式进行返回。

getDiary(long rowId)通过记录的主键id,得到特定的一条记录。

updateDiary(long rowId, String title, String body)更新主键id为rowId那条记录中的两个字段title和body字段的内容。

小知识 什么是ContentValues类?

ContentValues类和Hashtable比较类似,它也是负责存储一些名值对,但是它存储的名值对当中的名是一个String类型,而值都是基本类型。

我们回顾一下,在上一个例子当中,我们是通过SQL语句进行插入操作,SQL语句的好处是比较直观,但是容易出错。但是在这个例子当中我们有更好的办法,在这里我们将要插入的值都放到一个ContentValues的实例当中,然后执行插入操作,具体代码如下所示:

  1. public long createDiary(String title, String body) {  
  2.         ContentValues initialValues = new ContentValues();  
  3.         initialValues.put(KEY_TITLE, title);  
  4.         initialValues.put(KEY_BODY, body);  
  5.         Calendar calendar =  Calendar.getInstance();  
  6. // 生成年月日字符串  
  7.         String created = calendar.get(Calendar.YEAR) +"年"+calendar.get(Calendar. MONTH)+"月"+calendar.get (Calendar.DAY_OF_MONTH)+"日"+calendar.get(Calendar. HOUR_OF _DAY)+"时"+calendar.get(Calendar.MINUTE)+"分";  
  8.         initialValues.put(KEY_CREATED, created);  
  9.         return mDb.insert(DATABASE_TABLE, null, initialValues);  

代码解释:

ContentValues initialValues = new ContentValues()语句实例化一个contentValues类。

initialValues.put(KEY_TITLE, title)语句将列名和对应的列值放置到initialValues里边。

mDb.insert(DATABASE_TABLE, null, initialValues)语句负责插入一条新的纪录,如果插入成功则会返回这条记录的id,如果插入失败会返回-1。

在更新一条记录的时候,我们也是采用ContentValues 的这套机制,具体代码如下所示:

  1. public boolean updateDiary(long rowId, String title, String body) {  
  2. ContentValues args = new ContentValues();  
  3. args.put(KEY_TITLE, title);  
  4. args.put(KEY_BODY, body);  
  5. Calendar calendar = Calendar.getInstance();  
  6. String created = calendar.get(Calendar.YEAR) + "年" 
  7. + calendar.get(Calendar.MONTH) + "月" 
  8. + calendar.get(Calendar.DAY_OF_MONTH) + "日" 
  9. + calendar.get(Calendar.HOUR_OF_DAY) + "时" 
  10. + calendar.get(Calendar.MINUTE) + "分";  
  11. args.put(KEY_CREATED, created);  
  12.  
  13. return mDb.update(DATABASE_TABLE, args,  KEY_ROWID + "=" + rowId, null) > 0;  

代码解释:

实现更新一条记录。

4.第四步

现在返回到程序的主界面,对应的Activity是ActivityMain。

当我们单击menu按钮后会出现如图8-18所示界面。

 
(点击查看大图)图8-18  单击menu

 

 

根据我们第7章对menu的学习,对单击menu里边按钮的处理逻辑全部放在onMenuItem Selected函数里,具体代码如下所示:

  1. public boolean onMenuItemSelected(int featureId, MenuItem item) {  
  2. switch (item.getItemId()) {  
  3. case INSERT_ID:  
  4. createDiary();  
  5. return true;  
  6. case DELETE_ID:  
  7. mDbHelper.deleteDiary(getListView().getSelectedItemId());  
  8. renderListView();  
  9. return true;  
  10. }  
  11. return super.onMenuItemSelected(featureId, item);  

代码解释:

如果单击添加一篇新日记按钮那么会执行到createDiary()语句。

如果单击删除一条记录,会执行mDbHelper.deleteDiary(getListView().getSelectedItemId())语句,首先删除当前被选中的某一项所对应的数据库当中的记录。

renderListView()语句重新对界面刷新。

在createDiary()函数里边的代码如下所示:

  1. private void createDiary() {  
  2. Intent i = new Intent(this, ActivityDiaryEdit.class);  
  3. startActivityForResult(i, ACTIVITY_CREATE);  

代码解释:

首先构造了一个intent,这个intent负责跳转到ActivityDiaryEdit里。

然后启动这个intent,并且需要返回值。

5.第五步

在ActivityMain中,有多处地方都用到了renderListView()函数。在onCreate里边用这个函数显示ListView。当ListView需要发生变化后,例如,删除了一条记录或者增加了一条记录的时候,我们调用这个函数进行刷新ListView,下边来看一下此函数的实现,具体代码如下所示:

  1. private void renderListView() {  
  2. mDiaryCursor = mDbHelper.getAllNotes();  
  3. startManagingCursor(mDiaryCursor);  
  4. String[] from = new String[] { DiaryDbAdapter.KEY_TITLE,  
  5. DiaryDbAdapter.KEY_CREATED };  
  6. int[] to = new int[] { R.id.text1, R.id.created };  
  7. SimpleCursorAdapter notes = new SimpleCursorAdapter(this,  
  8. R.layout.diary_row, mDiaryCursor, from, to);  
  9. setListAdapter(notes);  

代码解释:

mDiaryCursor = mDbHelper.getAllNotes()语句,我们首先获取数据库当中的所有数据,这些数据以Cursor的形式存在。

startManagingCursor(mDiaryCursor)语句,我们将生成的Cursor交给Activity来管理,这样的好处是系统能自动做很多事情,比如当程序暂停的时候,这个系统可以卸载Cursor以节省空间,当程序重新启动的时候系统重新查询生成Cursor。

String[] from 里边定义了ListView每一排对应的数据是从数据库中的哪个列表里选取。

和SimpleAdapter类似 int[] to 里边是一个View的数组。这些View只能是TextView或者ImageView。这些View是以id的形式来表示的,如Android.R.id.text1。

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,R.layout.diary_row, mDiaryCursor, from, to)语句生成一个SimpleCursorAdapter ,我们介绍以下每一个参数的意义。

第一个参数是Context。

第二个参数为R.layout.diary_row,它关联在diary_row.xml文件当中定义的Layout,这个Layout规定ListView当中每一项的布局。

第三个参数就是Cursor。

第四个参数是数据表当中的列的数组,只有在这里边出现的列名,数据才会对应的填充在to里边对应的TextView或者ImageView当中。

第五个参数是在ListView里边每一项中需要被数据填充的TextView或者ImageView。

setListAdapter(notes)语句将SimpleCursorAdapter 和ListActivity里边的ListView绑定起来,至此在界面当中才会显示出列表来。

小知识 什么是SimpleCursorAdapter ?

在第7章,我们已经介绍过了ArrayAdapter和SimpleAdapter。和它们俩类似,SimpleCursorAdapter 也是集成Adapter。ArrayAdapter负责把一个字符串数组中的数据填充到一个ListView当中,而对应的SimpleCursorAdapter 负责把Cursor里边的内容填充到ListView当中。通过SimpleCursorAdapter 可以把数据库当中一列的数据和ListView中一排进行对应起来。和前两个Adapter类似,要求和数据进行对应的View必须是TextView或者ImageView。

6.第六步

单击添加一条数据的按钮,程序运行界面如图8-19所示。

 
(点击查看大图)图8-19  新建一篇日记的界面

 

 

这个界面对应的Activity是ActivityDiaryEdit,对应的布局文件是diary_edit.xml。对于这个布局文件里边用到了LinearLayout、TextView和EditText,这些我们都已经讲过,在这里不再赘述,具体看一下代码:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2.  
  3. <LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android" 
  4. Android:orientation="vertical" Android:layout_width="fill_parent" 
  5. Android:layout_height="fill_parent">  
  6.  
  7. <LinearLayout Android:orientation="vertical" 
  8. Android:layout_width="fill_parent" 
  9. Android:layout_height="wrap_content">  
  10.  
  11. <TextView Android:layout_width="wrap_content" 
  12. Android:layout_height="wrap_content" Android:text="@string/title" 
  13. Android:padding="2px" />  
  14. <EditText Android:id="@+id/title" 
  15. Android:layout_width="fill_parent" 
  16. Android:layout_height="wrap_content" Android:layout_weight="1" />  
  17. </LinearLayout>  
  18.  
  19. <TextView Android:layout_width="wrap_content" 
  20. Android:layout_height="wrap_content" Android:text="@string/body" />  
  21. <EditText Android:id="@+id/body" Android:layout_width="fill_parent" 
  22. Android:layout_height="wrap_content" Android:layout_weight="1" 
  23. Android:scrollbars="vertical" />  
  24.  
  25. <Button Android:id="@+id/confirm" Android:text="@string/confirm" 
  26. Android:layout_width="wrap_content" 
  27. Android:layout_height="wrap_content" />  
  28.  
  29. </LinearLayout> 

代码解释:

在一个LinearLayout里边我们放置了一些文本框、输入框和一些Button按钮。

当程序运行输入内容后,单击确定按钮,日记就会保存到数据库当中。下边来看一下代码具体是怎么执行的。当单击确定按钮后,系统回调执行和按钮绑定的单击监听器里边的onClick方法,具体代码如下所示:

  1. public void onClick(View view) {  
  2. String title = mTitleText.getText().toString();  
  3. String body = mBodyText.getText().toString();  
  4. if (mRowId != null) {  
  5. mDbHelper.updateDiary(mRowId, title, body);  
  6. else 
  7. mDbHelper.createDiary(title, body);  
  8. Intent mIntent = new Intent();  
  9. setResult(RESULT_OK, mIntent);  
  10. finish();  

代码解释:

首先获得EditView里边的数据。

目前mRowId 为null,所以执行mDbHelper.createDiary(title, body)语句将数据保存到数据当中。

setResult(RESULT_OK, mIntent)语句设置返回值。

执行完上边的代码后,系统跳转到ActivityMain,并执行回调函数onActivityResult,具体代码如下所示:

  1. protected void onActivityResult(int requestCode, int resultCode,  
  2. Intent intent) {  
  3. super.onActivityResult(requestCode, resultCode, intent);  
  4. renderListView();  

代码解释:

在回调函数中,我们重新对ListView进行刷新,将所有的数据重新显示出。

7.第七步

单击ListView里边的条列,可以对刚才保存的数据进行编辑。具体怎么实现这个功能的,我们可以看一下ActivityMain当中的onListItemClick方法代码:

  1. protected void onListItemClick(ListView l,  View v, int position, long id) {  
  2. super.onListItemClick(l, v, position, id);  
  3. Cursor c = mDiaryCursor;  
  4. c.moveToPosition(position);  
  5. Intent i = new Intent(this, ActivityDiaryEdit.class);  
  6. i.putExtra(DiaryDbAdapter.KEY_ROWID, id);  
  7. i.putExtra(DiaryDbAdapter.KEY_TITLE, c.getString (c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_TITLE)));  
  8. i.putExtra(DiaryDbAdapter.KEY_BODY, c.getString (c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_BODY)));  
  9. startActivityForResult(i, ACTIVITY_EDIT);  

代码解释:

c.moveToPosition(position)语句将在Cursor当中的指针移到position位置,这个position是我们单击的这个一列在整个列表中的位置。

Intent i = new Intent(this, ActivityDiaryEdit.class)语句构造一个跳转到ActivityDiaryEdit的intent。

putExtra()方法负责将要传递的数据放到intent当中。

c.getString(c.getColumnIndexOrThrow(DiaryDbAdapter.KEY_TITLE))得到这一条数据中列名为title的值。

c.getString(c.getColumnIndexOrThrow(DiaryDbAdapter.KEY_BODY))得到这一条数据中列名为body的值。

startActivityForResult(i, ACTIVITY_EDIT)语句启动intent,发生Activity的跳转。

我们来看一下ActivityDiaryEdit中的onCreate()里边的代码:

  1. Bundle extras = getIntent().getExtras();  
  2. if (extras != null) {  
  3. String title = extras.getString(DiaryDbAdapter.KEY_TITLE);  
  4. String body = extras.getString(DiaryDbAdapter.KEY_BODY);  
  5. mRowId = extras.getLong(DiaryDbAdapter.KEY_ROWID);  
  6.  
  7. if (title != null) {  
  8. mTitleText.setText(title);  
  9. }  
  10. if (body != null) {  
  11. mBodyText.setText(body);  
  12. }  

代码解释:

对于ActivityDiaryEdit这个Activity有两个intent可以跳转进来,一个是新建一篇日记的时候,这个时候intent里边的extras部分没有任何数据。第二种情况是在单击列表的某一个条列的时候,这个时候的intent如上所示会携带extras数据。所以在ActivityDiaryEdit中我们通过判断extras是否为null,就可以判断是哪种intent启动的。

当extras不为null,我们将extras里边的数据显示出来。

8.第八步

在程序的主界面当中,上下移动焦点(可以通过键盘的上下键或者模拟器中的上下按键),可以对拥有焦点的那一项进行删除,如图8-20、图8-21、图8-22所示。

 
(点击查看大图)图8-20  上下移动焦点界面
具体执行onMenuItemSelected中的代码:
  1. mDbHelper.deleteDiary(getListView().getSelectedItemId());  
  2. renderListView(); 

代码解释:

getListView()方法获取当前的ListView引用。

getSelectedItemId()方法得到当前这一列所对应的数据项的rowId,也就是这条数据在数据库中的主键id。

 
(点击查看大图)图8-21  进行删除界面
 
(点击查看大图)图8-22  删除后界面

mDbHelper.deleteDiary()方法删去数据库中的这一列数据。

renderListView()负责对列表重新刷新一遍。

至此,对数据库的学习就先告一段落,接下来将学习contentProvider,它是Android应用当中非常重要的一部分。而且程序间的大部分数据交换都是通过contentProvider机制进行。

 

分享到:
评论

相关推荐

    Android-Android数据库SQLite的简单使用实现我的便签

    Android 数据库SQLite的简单使用,实现我的便签

    android开发实例大全_王东华

    实例056: 编写一个手机日记本程序 170 实例057: 使用ContentProvider开发一个 手机日记本 177 实例058: 使用文件保存数据 188 实例059: 将网上的图片保存到SD卡并在 手机中显示出来 190 实例060: 保存联系人...

    android开发入门与实战(下)

    8.4.2 完整地操作数据库——日记本实例 8.5 我的数据你来用——ContentProvider介绍 8.5.1 初识ContentProvider 8.5.2 使用ContentProvider读取系统数据 8.5.3 使用ContentProvider操作数据日记本实例 8.6 再学一招...

    日记本实例

    本代码是日记本实例,用很大扩展性,里面有多可以学习的方面,特别对于数据库的操作以及ContentProvider的用法。用以和学习android的朋友参考,共同进步。

    Android的Sqlite数据存储

    Android四大存储方式之一-Sqlite数据存储,本实验以“日记本”的增删改查作为实例来使用SQLite

    android开发入门与实战(上)

    8.4.2 完整地操作数据库——日记本实例 8.5 我的数据你来用——ContentProvider介绍 8.5.1 初识ContentProvider 8.5.2 使用ContentProvider读取系统数据 8.5.3 使用ContentProvider操作数据日记本实例 8.6 再学一招...

    《Google Android开发入门与实战》.pdf

    8.4.2 完整地操作数据库——日记本实例 147 8.5 我的数据你来用——contentprovider介绍 155 8.5.1 初识contentprovider 155 8.5.2 使用contentprovider读取系统数据 156 8.5.3 使用contentprovider...

    Google.Android开发入门与实战

    8.4.2 完整地操作数据库——日记本实例 8.5 我的数据你来用——ContentProvider介绍 8.5.1 初识ContentProvider 8.5.2 使用ContentProvider读取系统数据 8.5.3 使用ContentProvider操作数据日记本实例 8.6 再学一招...

    Google Android开发入门与实战的代码

    8.4.2 完整地操作数据库——日记本实例 147 8.5 我的数据你来用——ContentProvider介绍 155 8.5.1 初识ContentProvider 155 8.5.2 使用ContentProvider读取系统数据 156 8.5.3 使用ContentProvider...

    利用sqlite实现最简单的android记事本

    通过sqlite实现最简单的记事本的增删改查

    Android 演示ContentProvider组件用法的写日记APP源码.rar

    本源码主要是演示Android ContentProvider组件的使用,借助一个写日记小程序来演示组件中各种方法的使用技巧,比如向日记本中插入一条数据,编辑当前数据内容、删除当前数据、查询cursor时候,感兴趣的那些条例如何...

    android写写心情

    安卓开发的日记本- 菜单  选项菜单  上下文菜单  子菜单 - 数据库  SQLite 适配器: - 把数据和视图结合在一起 - BaseAdapter  准备数据(以数组提供)  自己编写一个适配器类继承BaseAdapter  实现...

Global site tag (gtag.js) - Google Analytics