`
anson_xu
  • 浏览: 502245 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类

我的数据你来用—ContentProvider介绍

阅读更多

1.第一步

在Eclipse中,打开ex08_1_SQLite 项目,具体步骤如下。

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

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

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

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

2.第二步

单击运行项目,我们可以看到主界面如图8-7所示,这个界面的布局信息都在main.xml文件中,在一个LinearLayout当中数值排列了5个Button。

3.第三步

小知识

什么是SQLiteDatabase?

一个SQLiteDatabase的实例代表了一个SQLite的数据库,通过SQLiteDatabase实例的一些方法,我们可以执行SQL语句,对数据库进行增、删、查、改的操作。需要注意的是,数据库对于一个应用来说是私有的,并且在一个应用当中,数据库的名字也是惟一的。

          

                   ▲ 图8-6  程序目录结构图                                   ▲ 图8-7  主界面

小知识

什么是SQLiteOpenHelper ?

根据这名字,我们可以看出这个类是一个辅助类。这个类主要生成一个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法 getWritableDatabase()或者getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里边的3个函数,具体函数如下所示。

·  onCreate(SQLiteDatabase):在数据库第一次生成的时候会调用这个方法,一般我们在这个方法里边生成数据库表。

·  onUpgrade(SQLiteDatabase, int, int):当数据库需要升级的时候,Android系统会主动的调用这个方法。一般我们在这个方法里边删除数据表,并建立新的数据表,当然是否还需要做其他的操作,完全取决于应用的需求。

·  onOpen(SQLiteDatabase):这是当打开数据库时的回调函数,一般也不会用到。

我们在ActivityMain文件中看下边这个内部类。DatabaseHelper 类继承SQLiteOpenHelper ,具体代码如下所示:

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {

super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

// SQL语句

String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE

+ " text not null, " + BODY + " text not null " + ");";

Log.i("haiyang:createDB=", sql);

//执行这条SQL语句

db.execSQL(sql);

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

 代码解释:

·  DatabaseHelper类继承了SQLiteOpenHelper 类,并且重写了onCreate和onUpgrade方法。

·  在onCreate()方法里边首先我们构造一条SQL语句,然后调用db.execSQL(sql)执行SQL语句。这条SQL语句为我们生成了一张数据库表。

·  目前我们还不需要升级数据库,所以我们在onUpgrade()函数里边没有执行任何操作。

4.第四步

文本框:
▲ 图8-8  成功插入两条数据我们单击插入两条记录的按钮,如果数据成功插入到数据库当中的diary表中,那么在界面的title区域就会有成功的提示,如图8-8所示。

单击这个按钮后,程序执行了监听器里的onClick方法,并最终执行了上述程序里的insertItem方法,其具体代码如下所示:

private void insertItem() {

SQLiteDatabase db = mOpenHelper.getWritableDatabase();

//首先生成SQL语句

String sql1 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY

+ ") values('haiyang', 'Android的发展真是迅速啊');";

String sql2 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY

+ ") values('icesky', 'Android的发展真是迅速啊');";

try {

Log.i("haiyang:sql1=", sql1);

Log.i("haiyang:sql2=", sql2);

db.execSQL(sql1);

db.execSQL(sql2);

setTitle("插入两条数据成功");

} catch (SQLException e) {

setTitle("插入两条数据失败");

}

}

 代码解释:

·  SQLiteDatabase db = mOpenHelper.getWritableDatabase()这条语句负责得到一个可写的SQLite数据库,如果这个数据库还没有建立,那么mOpenHelper辅助类负责建立这个数据库。如果数据库已经建立,那么直接返回一个可写的数据库。

·  sql1和sql2是我们构造的标准的插入SQL语句,如果对SQL语句不是很熟悉,可以参考相关的书籍。鉴于本书的重点是在Android方面,所以对SQL语句的构建不进行详细的介绍。

·  Log.i()会将参数内容打印到日志当中,并且打印级别是Info级别,在使用LogCat工具的时候我们会进行详细的介绍。

·  db.execSQL(sql1)语句对SQL语句进行执行。

小知识

对Android的打印级别介绍

Android支持5种打印级别,分别是Verbose、Debug、Info、Warning、Error,当然我们在程序当中一般用到的是Info级别,即将一些自己需要知道的信息打印出来,如图8-9所示。

▲ 图8-9  Android中的5种打印级别

注意

虽然执行SQL语句在Android当中并没有强制放在try catch 语句当中,但是我们最好这么做。并在catch模块中将错误信息打印在日志当中。这样一方面是方便调试,另一方面可以加强程序的健壮性。

文本框:
▲ 图8-10  显示两条数据5.第五步

单击查询数据库的按钮,会在界面的title区域显示当前数据表当中数据的条数,刚才我们插入了两条,那么现在单击后应该显示为两条,如图8-10所示。

单击这个按钮后,程序执行了监听器里的onClick方法,并最终执行了上述程序里的showItems方法,具体代码如下所示:

private void showItems() {

SQLiteDatabase db = mOpenHelper.getReadableDatabase();

String col[] = { TITLE, BODY };

//进行数据库查询

Cursor cur = db.query (TABLE_NAME, col, null, null, null, null, null);

Integer num = cur.getCount();

setTitle(Integer.toString(num) + " 条记录");

}

 代码解释:

·  SQLiteDatabase db = mOpenHelper.getReadableDatabase()语句首先得到一个可写的数据库。

·  Cursor cur = db.query(TABLE_NAME, col, null, null, null, null, null)语句将查询到的数据放到一个Cursor 当中。这个Cursor里边封装了这个数据表TABLE_NAME当中的所有条列。 query()方法相当的有用,在这里我们简单地讲一下。

·  第一个参数是数据库里边表的名字,比如在我们这个例子,表的名字就是TABLE_NAME,也就是"diary"。

·  第二个字段是我们想要返回数据包含的列的信息。在这个例子当中我们想要得到的列有title、body。我们把这两个列的名字放到字符串数组里边来。

·  第三个参数为selection,相当于SQL语句的where部分,如果想返回所有的数据,那么就直接置为null。

·  第四个参数为selectionArgs。在selection部分,你有可能用到“?”,那么在selectionArgs定义的字符串会代替selection中的“?”。

·  第五个参数为groupBy。定义查询出来的数据是否分组,如果为null则说明不用分组。

·  第六个参数为having ,相当于SQL语句当中的having部分。

·  第七个参数为orderBy,来描述我们期望的返回值是否需要排序,如果设置为null则说明不需要排序。

·  Integer num = cur.getCount()语句通过getCount()方法,可以得到Cursor当中数据的个数。

小知识

什么是Cursor ?

Cursor 在Android当中是一个非常有用的接口,通过Cursor 我们可以对从数据库查询出来的结果集进行随机的读写访问。

6.第六步

单击删除一条数据库的按钮后,如果成功删除,我们可以看到在屏幕的标题(title)区域有文字提示,如图8-11所示。

现在我们再单击查询数据库按钮,看数据库里边的记录是不是少了一条。单击查询数据库按钮后,出现如图8-12所示的界面。

         

           ▲ 图8-11  成功删除一条记录                                ▲ 图8-12  还剩一条记录

下面我们来看一下如何删除数据。

单击删除一条记录的按钮后,程序执行了监听器里的onClick方法,并最终执行了上述程序里的deleteItem方法,其代码如下所示:

private void deleteItem() {

    try {

    SQLiteDatabase db = mOpenHelper.getWritableDatabase();

    //进行删除操作

    db.delete(TABLE_NAME, " title = 'haiyang'", null);

    setTitle("删除title为haiyang的一条记录");

    } catch (SQLException e) {

    }

    }

 代码解释:

·  db.delete(TABLE_NAME, " title = 'haiyang'", null)语句删除了一条title='haiyang'的数据。当然如果有很多条数据title都为'haiyang',那么一并删除。我们对delete方法的参数进行以下介绍。

·  第一个参数是数据库表名,在这里是TABLE_NAME,也就是diary。

·  第二个参数,相当于SQL语句当中的where部分,也就是描述了删除的条件。

文本框:
▲ 图8-13  删除数据库表·  如果在第二个参数当中有“?”符号,那么第三个参数中的字符串会依次替换在第二个参数当中出现的“?”符号。

7.第七步

单击删除数据表,我们可以删除diary这张数据表,如图8-13所示。

下边我们看在代码部分,是怎么实现删除的,具体代码如下所示:

private void dropTable() {

SQLiteDatabase db = mOpenHelper.getWritableDatabase();

String sql = "drop table " + TABLE_NAME;

try {

//执行SQL语句

db.execSQL(sql);

setTitle("数据表成功删除:" + sql);

} catch (SQLException e) {

setTitle("数据表删除错误");

}

}

 代码解释:

首先我们构造了一个标准的删除数据表的SQL语句,然后执行这条语句db.execSQL(sql)。

8.第八步

现在单击其他的按钮,程序运行时有可能会出现异常,我们单击重新建立数据表按钮,如图8-14所示。

现在我们单击查询数据库,看里边是否有数据,如图8-15所示。

下边我们看一下程序是如何建立一张新表的,具体实现代码如下所示:

private void CreateTable() {

     SQLiteDatabase db = mOpenHelper.getWritableDatabase();

     String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE

     + " text not null, " + BODY + " text not null " + ");";

          

             ▲ 图8-14  重新建立数据库表                         ▲ 图8-15  新建的表里边没有数据

     Log.i("haiyang:createDB=", sql);

     try {

     db.execSQL("DROP TABLE IF EXISTS diary");

     db.execSQL(sql);

     setTitle("数据表成功重建");

     } catch (SQLException e) {

     setTitle("数据表重建错误");

     }

     }

 代码解释:

·  sql变量表示的语句为标准的SQL语句,负责按要求建立一张新表。

·  db.execSQL("DROP TABLE IF EXISTS diary")语句表示,如果存在diary这张表,我们需要先删除,因为在同一个数据库当中不能出现两张同样名字的表。

·  db.execSQL(sql)语句执行SQL语句,新表建立。

8.4.2  完整地操作数据库——日记本实例

在上一个例子中,我们对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增加了升级的代码,具体如下所示:

private static class DatabaseHelper extends SQLiteOpenHelper {

         DatabaseHelper(Context context) {

             super(context, DATABASE_NAME, null, DATABASE_VERSION);

         }

         @Override

         public void onCreate(SQLiteDatabase db) {

//生成数据库

            db.execSQL(DATABASE_CREATE);

       

         @Override

         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

             db.execSQL("DROP TABLE IF EXISTS diary");

             onCreate(db);

         }

    }

 代码解释:

在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的实例当中,然后执行插入操作,具体代码如下所示:

public long createDiary(String title, String body) {

        ContentValues initialValues = new ContentValues();

        initialValues.put(KEY_TITLE, title);

        initialValues.put(KEY_BODY, body);

        Calendar calendar =  Calendar.getInstance();

// 生成年月日字符串

        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)+"分";

        initialValues.put(KEY_CREATED, created);

        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 的这套机制,具体代码如下所示:

public boolean updateDiary(long rowId, String title, String body) {

ContentValues args = new ContentValues();

args.put(KEY_TITLE, title);

args.put(KEY_BODY, body);

Calendar calendar = Calendar.getInstance();

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) + "分";

args.put(KEY_CREATED, created);

return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;

}

 代码解释:

文本框:
▲ 图8-18  单击menu实现更新一条记录。

4.第四步

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

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

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

public boolean onMenuItemSelected(int featureId, MenuItem item) {

switch (item.getItemId()) {

case INSERT_ID:

createDiary();

return true;

case DELETE_ID:

mDbHelper.deleteDiary(getListView().getSelectedItemId());

renderListView();

return true;

}

return super.onMenuItemSelected(featureId, item);

}

 代码解释:

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

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

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

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

private void createDiary() {

Intent i = new Intent(this, ActivityDiaryEdit.class);

startActivityForResult(i, ACTIVITY_CREATE);

}

 代码解释:

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

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

5.第五步

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

private void renderListView() {

mDiaryCursor = mDbHelper.getAllNotes();

startManagingCursor(mDiaryCursor);

String[] from = new String[] { DiaryDbAdapter.KEY_TITLE,

DiaryDbAdapter.KEY_CREATED };

int[] to = new int[] { R.id.text1, R.id.created };

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,

R.layout.diary_row, mDiaryCursor, from, to);

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所示。

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

文本框:
▲ 图8-19  新建一篇日记的界面

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"

Android:orientation="vertical" Android:layout_width="fill_parent"

Android:layout_height="fill_parent">

<LinearLayout Android:orientation="vertical"

Android:layout_width="fill_parent"

Android:layout_height="wrap_content">

<TextView Android:layout_width="wrap_content"

Android:layout_height="wrap_content" Android:text="@string/title"

Android:padding="2px" />

<EditText Android:id="@+id/title"

Android:layout_width="fill_parent"

Android:layout_height="wrap_content" Android:layout_weight="1" />

</LinearLayout>

<TextView Android:layout_width="wrap_content"

Android:layout_height="wrap_content" Android:text="@string/body" />

<EditText Android:id="@+id/body" Android:layout_width="fill_parent"

Android:layout_height="wrap_content" Android:layout_weight="1"

Android:scrollbars="vertical" />

<Button Android:id="@+id/confirm" Android:text="@string/confirm"

Android:layout_width="wrap_content"

Android:layout_height="wrap_content" />

</LinearLayout>

 代码解释:

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

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

public void onClick(View view) {

String title = mTitleText.getText().toString();

String body = mBodyText.getText().toString();

if (mRowId != null) {

mDbHelper.updateDiary(mRowId, title, body);

} else

mDbHelper.createDiary(title, body);

Intent mIntent = new Intent();

setResult(RESULT_OK, mIntent);

finish();

}

 代码解释:

·  首先获得EditView里边的数据。

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

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

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

protected void onActivityResult(int requestCode, int resultCode,

Intent intent) {

super.onActivityResult(requestCode, resultCode, intent);

renderListView();

}

 代码解释:

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

7.第七步

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

protected void onListItemClick(ListView l, View v, int position, long id) {

super.onListItemClick(l, v, position, id);

Cursor c = mDiaryCursor;

c.moveToPosition(position);

Intent i = new Intent(this, ActivityDiaryEdit.class);

i.putExtra(DiaryDbAdapter.KEY_ROWID, id);

i.putExtra(DiaryDbAdapter.KEY_TITLE, c.getString(c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_TITLE)));

i.putExtra(DiaryDbAdapter.KEY_BODY, c.getString(c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_BODY)));

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()里边的代码:

Bundle extras = getIntent().getExtras();

if (extras != null) {

String title = extras.getString(DiaryDbAdapter.KEY_TITLE);

String body = extras.getString(DiaryDbAdapter.KEY_BODY);

mRowId = extras.getLong(DiaryDbAdapter.KEY_ROWID);

if (title != null) {

mTitleText.setText(title);

}

if (body != null) {

mBodyText.setText(body);

}

}

 代码解释:

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

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

8.第八步

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

具体执行onMenuItemSelected中的代码:

mDbHelper.deleteDiary(getListView().getSelectedItemId());

renderListView();

 代码解释:

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

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

             

              ▲ 图8-21  进行删除界面                                  ▲ 图8-22  删除后界面

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

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

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

8.5  我的数据你来用——ContentProvider介绍

8.5.1  初识ContentProvider 

在第6章当中,介绍了组成Android程序的主要4部分,它们分别是。

·  Activity。

·  Broadcast Intent Receiver。

·  Service。

·  Content Provider。

关于Actvity和相关View的部分,已经在前边章节进行了比较详细的介绍,在这一节中,将学习Android应用里另外一个非常重要的部分ContentProvider。

1.什么是ContentProvider

Android这个系统和其他的操作系统还不太一样,读者需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。那这个时候有读者就会提出问题,难道两个程序之间就没有办法对于数据进行交换?Android这么优秀的系统不会让这种情况发生的。解决这个问题主要靠 ContentProvider。一个Content Provider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。也就是说,一个程序可以通过实

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics