简介
CursorLoader通常和LoaderManger、ContentProvider一起使用,简化数据库操作。本文介绍如何使用CursorLoader进行多表查询数据库操作,并将结果加在cursor结果集增加一列。以及介绍contactProvider刷新数据时遇到的小问题。
CursorLoader 使用多表查询方式
cursorLoader封装了contentProvider的查询操作,创建cursorLoader入参分为几个部分
-
DataContentProvider.Data_URI : ContactProvider的URI
-
PROJECTION : 要查询的字段
-
Columns.COLUMNS_A + “=1” :查询条件
1
2
3
4
loader = new BoundCursorLoader(bindingId, mContext,
DataContentProvider.Data_URI,
PROJECTION,
Columns.COLUMNS_A + "=1", null, null)
通常我们的查询条件比较复杂,可能涉及到多个表查询的复杂查询语句,这时要把查询条件塞到PROJECTION字段里。此时的Cursor则会多出现一列 。
例如如下代码,查询A表时,又查询了B表,使用 as 作为查询结果 用查询结果作为 ADDCLUME 字段的值,为Cursor 增加了一个数据库表中不存在的字段, 并将结果新增了一列ADDCLUME
1
2
3
4
5
6
7
8
9
10
public static final String[] PROJECTION = {
TABLE_A_COLUMN.COLUMN_A,
TABLE_A_COLUMN.COLUMN_B,
"(SELECT count(" + DatabaseHelper.TABLE_B + '.' + TABLE_B_COLUMN._ID + ")"
+ " FROM " + DatabaseHelper.TABLE_B
+ " LEFT JOIN " + DatabaseHelper.TABLE_A + " ON (" + DatabaseHelper.TABLE_A + "." + TABLE_A_COLUMN._ID + "=" + DatabaseHelper.TABLE_B + '.' + TABLE_B_COLUMN.CONVERSATION_ID + ")"
+ " WHERE "
+ TABLE_B_COLUMN.READ + " = 0 AND " + TABLE_A_COLUMN.ENTERPRISE_FLAG + "=1
") AS " + TABLE_A_COLUMN.ADDCLUME,
};
LoaderManager 使用
LoaderManger封装了CursorLoader创建销毁和执行,并且封装了回调接口
LoaderManager封装了异步操作,创建Loader后,数据查询结果通过onLoadFinished返回,到此便获得了cursor数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private class MyLoaderManager implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
switch (id) {
case LOADER_FLAG_A:
loader = new BoundCursorLoader(bindingId, mContext,
DataContentProvider.Data_URI,
PROJECTION,
SELECTION,
null,
SORT_ORDER);
break;
}
return loader;
}
@Override
public void onLoadFinished(final Loader<Cursor> generic, final Cursor data) {
switch (loader.getId()) {
case LOADER_FLAG_A:
//todo notify data loader
break;
default:
Assert.fail("Unknown loader id");
break;
}
}
@Override
public void onLoaderReset(final Loader<Cursor> generic) {
switch (loader.getId()) {
case LOADER_FLAG_A:
//todo notify data change
break;
}
}
}
通知刷新方式
CursorLoader内部已经封装了对URI的监听,因此只需要在数据发生改变时调用contactProvider的通知方法即可
1
2
3
4
5
6
public class DataContentProvider extends ContentProvider {
final ContentResolver cr = Factory.get().getApplicationContext().getContentResolver();
cr.notifyChange(Data_URI, null);
}
这里需要注意的是在后台无法通知刷新数据,frameWork框架做了限制,需要加上此Flag才能在后台通知
1
2
3
public class DataContentProvider extends ContentProvider {
cr.notifyChange(Data_URI, null, NOTIFY_NO_DELAY | ContentResolver.NOTIFY_SYNC_TO_NETWORK);
}
cursorLoader 分页
1,cursor一次性加载所有数据不会延迟吗?