Hello Android学习之SQLite(二)
来源:互联网 发布:求积分的软件 编辑:程序博客网 时间:2024/05/12 21:23
上节说到当我们遇到成百上千的语句时查找数据库内容该怎么办,Android提供了一个更加好的办法,那就是Data Binding,它允许我们从数据库到试图仅仅少量的代码。为了演示Data Binding我们来修改上次的代码。
1. 首先来修改Event.java,让其继承ListActivity类代替Activity类。
2. 我们需要修改showEvent方法,代码如下:
private static int[] TO ={R.id.rowid,R.id.time,R.id.title}; private void showEvents(Cursor cursor){ //Set up data binding SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, FROM, TO); setListAdapter(adapter); }
你会发现代码比以前少了很多,我们为Cursor方法创建了SimpleCursorAdapter,然后告诉ListActivity来用这个新的adapter,这个adapter把View和数据库连接了一来。SimpleCursorAdapter中有五个参数:
context:是指现在所用的Activity。
Layout:试图(View)所在的资源,也就是路径。
Cursor:数据库连接用的cursor。
From:列表每个的名字,也就是数据是从哪里来的
To:这些数据是到那里的试图
3. 新增一个列表定义在layout/item.xml中,你会发现这里的row ID,time,title将会被TO引用。代码如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:padding="10sp"> <TextView android:id="@+id/rowid" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/rowidcolon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=":" android:layout_toRightOf="@id/rowid"/> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/rowidcolon"/> <TextView android:id="@+id/timecolon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=":" android:layout_toRightOf="@id/time"/> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:ellipsize="end" android:singleLine="true" android:textStyle="italic" android:layout_toRightOf="@id/timecolon"/></RelativeLayout>
4. 修改layout/main.xml中的代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"><ListView android:id="@android:id/list" android:layout_width="wrap_content" android:layout_height="wrap_content"/><TextView android:id="@android:id/empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/empty"/></LinearLayout>
由于这个activity是继承ListActivity的,android寻找两个特别的layout文件,如果列表中已经存在文件,则会调用android:id/list来展示view,否则会调用android:id/empty来显示No events.
5. 添加strings.xml文件中的内容如下:
<string name="app_name">Events</string><string name="empty">No events!</string>
这时你就会看见不一样的效果了,新的问题又出现了,当用户选择一条数据,当他选择想看其中的内容的时候或者想要删除这条数据,将要怎么办呢?但是没有什么应用程序是来进行这样的操作的,所以我们需要用到ContentProvider。
在Android安全模型中,一个应用程序编写的文件无法被其他任何应用程序所读写。每个程序都有自己的Linux用户ID和数据目录(data/data/包名),以及其受保护的内存空间。Android程序可通过下面两种方式进行彼此间的通信。
a. IPC(Inter-Process Communication,进程间通信):一个进程使用AIDL(接口定义语言)和Ibinder接口声明一个任意的API。调用该API时,将在进程间安全且有效地对参数进行编组,这项先进技术用于对后台Service线程进行远程过程调用。
b. ContentProvider:进程中系统中将它们本身注册为某些数据类型的提供者。请求信息时,Android就会通过一个固定的API调用这些进程,以它们认为合适的方式查询或修改内容。
任何信息在被ContentProvider处理时,都会通过URI格式为 content://authority/path/id 。
其中的参数为:
content://是标准要求的前缀;
authority:是提供者的名称,建议你使用完全限定包名称,避免出现名称冲突;
path:是提供者内部的一个虚拟目录,用于标识被请求的数据类型;
id:是被请求的特定记录的主键,要请求获得具有特定类型的所有记录,可以省略此参数以及后面的斜杠。
6.所以我们需要多增加两个常量到Constants.java中。
7. 改变主程序中onCreate()代码如下:
package com.zy.events;import static com.zy.events.Constants.TIME;import static com.zy.events.Constants.TITLE;import static android.provider.BaseColumns._ID;import static com.zy.events.Constants.CONTENT_URI;import android.app.ListActivity;import android.content.ContentValues;import android.database.Cursor;import android.os.Bundle;import android.widget.SimpleCursorAdapter;public class Events extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);addEvent("Hell,Android!");Cursor cursor = getEvents();showEvents(cursor); } private void addEvent(String string){ //Insert a new record into the Events data source. //You would do something similar for delete and update. ContentValues values = new ContentValues(); values.put(TIME, System.currentTimeMillis()); values.put(TITLE, string); getContentResolver().insert(CONTENT_URI, values); } private static String[] FROM ={_ID,TIME,TITLE}; private static String ORDER_BY = TIME + " DESC"; private Cursor getEvents(){ //Perform a managed query. The Activity will handle cloding //and re-querying the cursor when needed. return managedQuery(CONTENT_URI, FROM, null, null, ORDER_BY); } private static int[] TO ={R.id.rowid,R.id.time,R.id.title}; private void showEvents(Cursor cursor){ //Set up data binding SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, FROM, TO); setListAdapter(adapter); }}
8. 新增EventsProvider继承于ContentProvider:
ContentProvider是一个类似于Activity的高级对象,需要向系统进行声明。因此,实现ContentProvider的第一步是将其添加到AndroidManifest.xml文件中的<activity>标签之前(作为<application>的子标签)。
<provider android:name=”EventsProvider”
android:authorities=”com.zy.events” />
android:name是类名,android:authorities是在内容URI中使用的字符串。
EventsProvider.java代码如下:
package com.zy.events;import static android.provider.BaseColumns._ID;import static com.zy.events.Constants.AUTHORITY;import static com.zy.events.Constants.CONTENT_URI;import static com.zy.events.Constants.TABLE_NAME;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.net.Uri;import android.text.TextUtils;public class EventsProvider extends ContentProvider { private static final int EVENTS = 1; private static final int EVENTS_ID = 2; /** The MIME type of a directory of events */ private static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.example.event"; /** The MIME type of a single event */ private static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.example.event"; private EventsData events; private UriMatcher uriMatcher; // ... @Override public boolean onCreate() { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "events", EVENTS); uriMatcher.addURI(AUTHORITY, "events/#", EVENTS_ID); events = new EventsData(getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) { if (uriMatcher.match(uri) == EVENTS_ID) { long id = Long.parseLong(uri.getPathSegments().get(1)); selection = appendRowId(selection, id); } // Get the database and run the query SQLiteDatabase db = events.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy); // Tell the cursor what uri to watch, so it knows when its // source data changes cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case EVENTS: return CONTENT_TYPE; case EVENTS_ID: return CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unknown URI " + uri); } } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = events.getWritableDatabase(); // Validate the requested uri if (uriMatcher.match(uri) != EVENTS) { throw new IllegalArgumentException("Unknown URI " + uri); } // Insert into database long id = db.insertOrThrow(TABLE_NAME, null, values); // Notify any watchers of the change Uri newUri = ContentUris.withAppendedId(CONTENT_URI, id); getContext().getContentResolver().notifyChange(newUri, null); return newUri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = events.getWritableDatabase(); int count; switch (uriMatcher.match(uri)) { case EVENTS: count = db.delete(TABLE_NAME, selection, selectionArgs); break; case EVENTS_ID: long id = Long.parseLong(uri.getPathSegments().get(1)); count = db.delete(TABLE_NAME, appendRowId(selection, id), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } // Notify any watchers of the change getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = events.getWritableDatabase(); int count; switch (uriMatcher.match(uri)) { case EVENTS: count = db.update(TABLE_NAME, values, selection, selectionArgs); break; case EVENTS_ID: long id = Long.parseLong(uri.getPathSegments().get(1)); count = db.update(TABLE_NAME, values, appendRowId( selection, id), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } // Notify any watchers of the change getContext().getContentResolver().notifyChange(uri, null); return count; } /** Append an id test to a SQL selection expression */ private String appendRowId(String selection, long id) { return _ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); }}
这个显示效果如上图,现在我们已经有了事件存储的框架了,这样就可以被其他的应用程序所用,甚至被其他的程序员来进行开发。
- Hello Android学习之SQLite(二)
- Hello Android学习之SQLite(一)
- Android之SQLite 学习二
- Android 学习之二:安装开发环境与Hello World
- Android学习之SQLite
- Android之SQLite学习
- Android学习之SQLite
- Android学习之SQLite
- Android学习之SQLite
- Android之SQLite学习
- SQLite学习笔记之二
- SQLite学习笔记之二
- Android下SQLite数据库编程学习系列之二---在Android下使用SQLite
- Android学习之SQLite学习
- android之SQLite使用心得之二
- android学习笔记之SQLite
- Android学习 之 Sqlite小结
- Android学习笔记之SQLite
- 如何进行java系统优化
- OpenVPN关于push-peer-info的实现
- C#之P/Invoke
- C语言中字符数组和字符串指针分析
- Qt程序 与 CMD窗口弹出的控制
- Hello Android学习之SQLite(二)
- 在Linux下玩拳皇(不是Wine的)
- C++--2
- 窗外的雨
- Android 学习 开发环境搭建
- python PyQt4库使用入门
- 希波克拉底誓言
- eclipse maven 插件
- cut