如何通过contentProvider实现groupby查询数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何通过contentProvider实现groupby查询数据相关的知识,希望对你有一定的参考价值。

参考技术A 比如要用实现这么一个sql语句:
SELECT _id, number, date, duration, type, name, numbertype,
numberlabel, COUNT(*) FROM calls GROUP BY number,type,date/8640000
ORDER BY date DESC
这个在一般的SQL编译工具里都能正常运行,在ContentRosolver中有些不一样。

用ContentRosolver中的query这么写:

private static String CALLS_COUNT = "calls_count";
static final String[] CALL_LOG_PROJECTION = new String[]
Calls._ID,
Calls.NUMBER,
Calls.DATE,
Calls.DURATION,
Calls.TYPE,
Calls.CACHED_NAME,
Calls.CACHED_NUMBER_TYPE,
Calls.CACHED_NUMBER_LABEL,
"COUNT(*) AS " + CALLS_COUNT
;

String selection = "0==0) GROUP BY ("+
Calls.NUMBER+"),("+
Calls.TYPE+"),("+
Calls.DATE+"/86400000";

rosolver.query(QUERY_TOKEN, null, Calls.CONTENT_URI,
CALL_LOG_PROJECTION, selection, null, Calls.DEFAULT_SORT_ORDER);

注意事项:
1 关键字“COUNT, AS, GROUP BY”的大小写
2 COUNT(*) 后需要跟AS ***
3 android会将query中的参数整合成一条sql语句,其中会将selection的字符串自动加一个括号,形成 “WHERE
(*******)”的形式,所以要特别注意selection中有括号的情况
4 GROUP BY后面的字段应该加括号,用逗号隔开。

转化为sql语句正确的形式应该如下:
SELECT _id, number, date, duration, type, name, numbertype,
numberlabel, COUNT(*) FROM calls WHERE (0==0) GROUP BY
(number),(type),(date/8640000) ORDER BY date DESC

希望能帮到你!本回答被提问者和网友采纳
参考技术B SELECT _id, number, date, duration, type, name, numbertype,
numberlabel, COUNT(*) FROM calls GROUP BY number,type,date/8640000
ORDER BY date DESC
这个在一般的SQL编译工具里都能正常运行,在ContentRosolver中有些不一样。

用ContentRosolver中的query这么写:

private static String CALLS_COUNT = "calls_count";
static final String[] CALL_LOG_PROJECTION = new String[]
Calls._ID,
Calls.NUMBER,
Calls.DATE,
Calls.DURATION,
Calls.TYPE,
Calls.CACHED_NAME,
Calls.CACHED_NUMBER_TYPE,
Calls.CACHED_NUMBER_LABEL,
"COUNT(*) AS " + CALLS_COUNT
;

String selection = "0==0) GROUP BY ("+
Calls.NUMBER+"),("+
Calls.TYPE+"),("+
Calls.DATE+"/86400000";

rosolver.query(QUERY_TOKEN, null, Calls.CONTENT_URI,
CALL_LOG_PROJECTION, selection, null, Calls.DEFAULT_SORT_ORDER);

注意事项:
1 关键字“COUNT, AS, GROUP BY”的大小写
2 COUNT(*) 后需要跟AS ***
3 Android会将query中的参数整合成一条sql语句,其中会将selection的字符串自动加一个括号,形成 “WHERE
(*******)”的形式,所以要特别注意selection中有括号的情况
4 GROUP BY后面的字段应该加括号,用逗号隔开。

转化为sql语句正确的形式应该如下:
SELECT _id, number, date, duration, type, name, numbertype,
numberlabel, COUNT(*) FROM calls WHERE (0==0) GROUP BY
(number),(type),(date/8640000) ORDER BY date DESC

自己实现第一个ContentProvider

一、概念及说明

ContentProvider定义:

内容提供者是一个android应用的基础模块,提供内容给这个应用,它们封装数据和提供它给应用通过这个ContentResolver接口,使用ContentProvider可以在不同的应用程序之间共享数据,android为常见的一些数据提供了ContentProvider(视频、音频),ContentProvider使用表的形式来组织数据。

 URI定义:

每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。android所提供ContentProvider都存放在android.provider。


二、实现ContentProvider的过程

1。定义ContentProvider所需要的常量(最主要的是定义CONTENT_URI,CONTENT_URI是Uri类型,事实是通过字符串解析得到)

//定义ContentProvider所需要的常量
public class FirstProviderMetaData 

	// AUTHORIY等于自己的创建ContentProvider类的完全路径
	public static final String AUTHORIY = "com.example.firstconent.FirstContentProvider";

	// 数据库的名称
	public static final String DATABASE_NAME = "FirstProvider.db";

	// BaseColumns有两个字段_id和_count
	public static final class UserTableMetaData implements BaseColumns 
		// 表名
		public static final String TABLE_NAME = "t_user";
		// 访问该ContentProvider的URI
		public static final Uri CONTENT_URI = Uri
				.parse("content://" + AUTHORIY);

		// 表的数据类型
		public static final String CONTENT_TYPE = "vnd.android.cursor.dir/users";
		// 一列的数据类型
		public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/users";

		// 一个字段
		public static final String USER_NAME = "name";

		// 默认排序
		public static final String DEFAULT_SORT_ORDER = "_id desc";
	

2。定义一个类,继承ContentProvider

3。实现query,insert,update,delete,getType和onCreate方法


(1).定义UriMatcher

// 匹配Uri,检查Uri的合法性
	public static final UriMatcher uriMatcher;
	public static final int INCOMING_USER_COLLECTION = 1;
	public static final int INCOMING_USER_SIGNLE = 2;
	static 
		// 创建一个uri树的根结点
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		// 添加uri匹配对,如果这个匹配成功,则code值则会返回。
		uriMatcher.addURI(FirstProviderMetaData.AUTHORIY, "/t_user",
				INCOMING_USER_COLLECTION);
		uriMatcher.addURI(FirstProviderMetaData.AUTHORIY, "/t_user/#",
				INCOMING_USER_SIGNLE);

	

(2).重写getType方法

// 根据传入uri,所回该uri所表示的数据类型
	@Override
	public String getType(Uri uri) 
		// TODO Auto-generated method stub
		switch (uriMatcher.match(uri)) 
		case INCOMING_USER_COLLECTION:
			return UserTableMetaData.CONTENT_TYPE;
		case INCOMING_USER_SIGNLE:
			return UserTableMetaData.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		

	
(3).创建userProjectMap哈希Map静态对象

public static HashMap<String, String> userProjectMap;
	static 
		userProjectMap = new HashMap<String, String>();
		userProjectMap.put(UserTableMetaData._ID, UserTableMetaData._ID);
		userProjectMap.put(UserTableMetaData.USER_NAME,
				UserTableMetaData.USER_NAME);
	

(4).重写insert方法

// 该方法返回值是一个uri,这个uri表示的刚刚使用这个方法所插入的数据
	@Override
	public Uri insert(Uri uri, ContentValues values) 
		// TODO Auto-generated method stub
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		// rowId是新插入数据的id
		long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
		// 正常插入,-1为出常错误
		if (rowId != -1) 
			// 添加一个id到这个路径的结尾
			Uri insertUserUri = ContentUris.withAppendedId(
					UserTableMetaData.CONTENT_URI, rowId);
			// 得到一个ContentResolver实例.
			ContentResolver cr = this.getContext().getContentResolver();
			// 通辞呈数据改变
			cr.notifyChange(insertUserUri, null);

			return insertUserUri;
		 else 
			throw new SQLException("Failed to insert row into" + uri);
		
	
(5).重写query方法

@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) 
		// TODO Auto-generated method stub
		SQLiteQueryBuilder sqb = new SQLiteQueryBuilder();
		switch (uriMatcher.match(uri)) 
		case INCOMING_USER_COLLECTION:
			sqb.setTables(UserTableMetaData.TABLE_NAME);
			sqb.setProjectionMap(userProjectMap);
			break;
		case INCOMING_USER_SIGNLE:
			sqb.setTables(UserTableMetaData.TABLE_NAME);
			sqb.setProjectionMap(userProjectMap);

			String idKey = UserTableMetaData._ID;
			// 1得到path集合
			// 2取它的集合的第2个元素
			// 例如:CONTENT_URI等于content://com.example.firstconent.FirstContentProvider/t_user/id,
			// content://为协议
			// com.example.firstconent.FirstContentProvider为authoriy
			// /t_user/id为path
			String idValue = uri.getPathSegments().get(1);

			sqb.appendWhere(idKey + "=" + idValue);
			break;
		
		String orderBy = null;
		if (TextUtils.isEmpty(sortOrder)) 
			orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
		 else 
			orderBy = sortOrder;
		
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		Cursor cursor = sqb.query(db, projection, selection, selectionArgs,
				null, null, orderBy);
		ContentResolver cr = this.getContext().getContentResolver();
		// 通适数据变动
		cursor.setNotificationUri(cr, uri);
		return cursor;
	

4。在AndroidManifest.xml中声明

<provider
            android:name="com.example.firstcontent.FirstContentProvider"
            android:authorities="com.example.first.firstcontent.FirstContentProvider" >
        </provider>



以上是关于如何通过contentProvider实现groupby查询数据的主要内容,如果未能解决你的问题,请参考以下文章

如何通过contentProvider实现groupby查询数据

如何通过contentProvider实现groupby查询数据

自己实现第一个ContentProvider

android-ContentProvider

LeakCanary使用学习(未完)

ContentProvider学习笔记