- 浏览: 513126 次
- 性别:
- 来自: 惠州
文章分类
- 全部博客 (255)
- ant (1)
- springMVC (2)
- ajax (4)
- oracle (12)
- SSH (13)
- struts1 (2)
- Hibernate (14)
- spring (5)
- jstl (1)
- 连接池 (1)
- acegi (4)
- java (17)
- jquery (11)
- div+css (4)
- drupal (1)
- php (8)
- freemaker调模板生成静态页面 (1)
- xml (1)
- json (2)
- javascript (9)
- 正则表达式 (4)
- Ext (8)
- jdbc (1)
- sql server (2)
- perl (5)
- db4o (1)
- webservice (4)
- flex (13)
- it资讯 (1)
- joomla (0)
- 设计模式 (1)
- struts2 (4)
- s2sh (8)
- linux (3)
- ejb (2)
- android旅途 (24)
- android (36)
- C/C++ (16)
- mysql (1)
最新评论
-
fengyuxing168:
IBelyService bs = IBelyService. ...
为 Android 添加 Java 层服务也就是添加自定义的aidl服务到serviceManager 通过ServiceManager.getService取 -
dengzhangtao:
"由于ActivityManagerService是 ...
binder理解 -
yzyspy:
ActivityManagerService:startHom ...
Android的Launcher成为系统中第一个启动的,也是唯一的 -
Matchstick:
使用SELECT DISTINCT alias FROM Po ...
hibernate 一对多表查询时fetchMode.join 生成left outer join 出来数据重复问题 -
dlheart:
没看懂你什么意思啊,我遇到的问题是一对多,设了fetch = ...
hibernate 一对多表查询时fetchMode.join 生成left outer join 出来数据重复问题
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.第四步
我们单击插入两条记录的按钮,如果数据成功插入到数据库当中的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模块中将错误信息打印在日志当中。这样一方面是方便调试,另一方面可以加强程序的健壮性。 |
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部分,也就是描述了删除的条件。
· 如果在第二个参数当中有“?”符号,那么第三个参数中的字符串会依次替换在第二个参数当中出现的“?”符号。
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;
}
代码解释:
实现更新一条记录。
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,这些我们都已经讲过,在这里不再赘述,具体看一下代码:
<?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);
}
}
代码解释:
· 对于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的各种数据类型。也就是说,一个程序可以通过实
发表评论
-
Android display架构分析
2011-11-08 14:43 2602Android display架构分析 高通7系列硬件架 ... -
android usb流程(转载加整理)
2011-11-08 14:42 3136android usb流程(转载加整理) ... -
C++友元friend --c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作
2011-09-08 16:36 966<!-- [if gte mso 9]><x ... -
Jni函数调用大全
2011-09-08 16:34 9784Jni函数调用 ... -
android linux 基础知识总结
2011-09-08 16:23 2848android linux 基础知识总结 ===== ... -
pthread_create用法 c线程
2011-09-08 09:34 3636今天开始学习linux下用C开发多线程程序,Linux系统下的 ... -
C++多线程入门(一)
2011-09-05 14:32 1243第1节 背景 为了更好的理解多线程的概念,先对进程,线程 ... -
C++中的虚函数(virtual function)多态
2011-09-05 13:41 9301.简介 虚函数是 ... -
添加一个系统服务sytem service
2011-09-02 15:51 2507方法一: 1.在应用中 com.xxx.spi.SPLLi ... -
android.mk文件
2011-09-02 13:51 1249<!-- [if gte mso 9]><x ... -
android 中使用socket使native和framework通信
2011-09-01 10:14 1203android 中使用socket使native和frame ... -
让你自己写的Android的Launcher成为系统中第一个启动的,也是唯一的Launcher
2011-09-01 09:49 908[转]让你自己写的Android的Launcher成为系统中第 ... -
No implementation found for native Landroid/
2011-08-31 17:30 2423No implementation ... -
Java 线程中的Join、wait、notify,sleep【转】
2011-05-30 09:37 1088Java 线程中的Join、wait、notify ... -
android回调函数总结
2011-02-14 13:26 4385回调函数就是那些自己写的,但是不是自己来调,而是给别人来掉的函 ... -
IPC框架分析 Binder,Service,Service manager
2011-01-22 13:10 1317IPC框架分析 Binder,Servic ... -
Android中几种图像特效处理的小技巧,比如圆角,倒影,还有就是图片缩放,Drawable转化为Bitmap,Bitmap转化为Drawable等等
2011-01-22 11:41 2212Android中几种图像特效处理的小技巧,比如圆角,倒影,还有 ... -
Android中SurfaceView的使用示例
2011-01-19 20:54 880SurfaceView在游戏开发中有着举足轻重的地位,它对于画 ... -
Android 的 SurfaceView 双缓冲应用
2011-01-19 20:46 1803双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于Surfa ... -
Android Content Provider[转]
2010-10-21 14:42 1190Android应用程序可以使用 ...
相关推荐
"使用ContentProvider共享数据"这个主题涉及到如何构建和使用ContentProvider来开放数据库,以及如何通过ContentResolver来执行对这些共享数据的操作。 首先,理解ContentProvider的结构至关重要。ContentProvider...
该文件中有两个应用,db应用通过ContentProvider对外提供数据共享,other应用提供测试代码对数据进行增删改查。 参考博客:http://blog.csdn.net/tan313/article/details/44338425
3. **SQLite数据库集成**:如果你的数据存储在SQLite中,ContentProvider通常会结合SQLiteOpenHelper来管理数据库版本和创建表。 三、ContentProvider注册 1. **AndroidManifest.xml**:在应用的清单文件中,需要...
本篇文章将深入探讨如何使用ContentProvider来共享生词本数据。首先,我们来看看什么是ContentProvider。 ContentProvider是Android四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它的...
总结来说,ContentProvider是Android平台中实现数据共享的关键组件,通过定义Uri、注册到Manifest以及重写核心方法,我们可以创建一个能够跨应用共享数据的ContentProvider。同时,配合CursorLoader和LoaderManager...
在 Android 中,ContentProvider 是一个抽象的类,它提供了一种方式来存储和管理数据。它可以将数据暴露给其他应用程序,以便它们可以访问和操作这些数据。ContentProvider 可以提供多种类型的数据,包括数据库、...
下面将详细介绍ContentProvider数据共享的基本使用方法。 1. 创建ContentProvider 要创建一个ContentProvider,你需要继承`android.content.ContentProvider`类,并重写其中的关键方法,如`onCreate()`, `query()`,...
本教程将深入探讨如何使用ContentProvider来实现数据共享。 ### 一、ContentProvider基本概念 1. **组件角色**:ContentProvider作为Android四大组件之一,主要负责数据的读写操作,提供统一的接口供其他应用调用...
本文将深入探讨这两个技术,并结合实际案例,解释如何在Android应用中使用它们来管理和共享SQLite数据库。 首先,让我们从Android Room开始。Room是Google推出的Android架构组件之一,它提供了一个方便的SQL方言...
本篇将深入探讨如何使用ContentProvider对外共享数据以及如何监听内容提供者中的数据变化。 一、ContentProvider基础 ContentProvider是Android四大组件之一,它负责管理应用程序的数据,并提供统一的接口供其他...
实验8的内容主要涉及Android开发中的数据共享机制,具体是通过`ContentProvider`来实现的。`ContentProvider`是Android系统中用于不同应用程序间共享数据的一种核心组件。在本实验中,我们将学习如何创建和使用`...
在Android开发中,ContentProvider是四大组件之一,它扮演着数据共享的角色,使得不同应用程序间可以安全地访问和操作数据...在实际开发中,掌握ContentProvider的使用能让你更好地管理和共享应用数据,提升用户体验。
通过ContentProvider,我们可以将对数据库的操作封装起来,使得外部应用可以通过ContentProvider提供的接口来访问和修改数据,而无需直接访问数据库,增加了数据的安全性和隐私保护。 接下来,ContentResolver是另...
本文将详细介绍 ContentProvider 的主要功能、运行时权限的简介、机制设计和代码示例。 ContentProvider 的主要功能 ------------------------- ContentProvider 是 Android 中的一种机制,用于在不同的应用程序...
在本教程中,我们将深入探讨如何利用ContentProvider来操作文件,以及其在跨应用数据传输中的作用。 一、ContentProvider基础 1. ContentProvider概述:ContentProvider是Android四大组件之一,它的主要职责是管理...
ContentProvider通过URI(统一资源标识符)来识别和访问数据,每个数据集都有一个唯一的URI。 创建ContentProvider的步骤如下: 1. **定义URI**: 创建一个内部类,继承自`UriMatcher`,用于匹配不同的URI请求。为...
有了数据库支持后,你可以在ContentProvider的CRUD方法中使用SQL语句来操作数据。例如,在`query()`方法中,你可以通过SQL查询获取数据,然后将查询结果转换为Cursor对象返回: ```java @Override public Cursor ...
`ch11_contact_content_provider`可能涉及的是如何创建一个用于管理联系人的自定义ContentProvider,这通常涉及到对SQLite数据库的操作,因为大多数ContentProvider都会使用SQLite存储数据。`ch11_permission_region...
1. **定义Uri匹配规则**:ContentProvider通过Uri(统一资源标识符)来识别和操作数据。在`AndroidManifest.xml`文件中声明`<provider>`标签,并在对应的ContentProvider类中创建一个内部类继承自`UriMatcher`,用于...