您的位置:首页 > 移动开发 > Android开发

Android组件(Content Provider)

2016-05-19 15:41 645 查看
1.目录:

1.Content Provider概述

2.Content Provider共享数据过程

3.Content Provider作用

4.Content Provider创建

5.Content Provider数据管理(数据的增删改查)

6.访问Content Provider获取数据

7.UriMatcher & Uri

2.Content Provider概述:

Content Provider(内容提供者),明白它的含义我们的明白两点,内容是啥?提供给谁?

OK,内容即数据,来自File或者sqlite数据库,该组件主要用于建立一个统一的接口

提供给其他应用访问自己应用数据,同时也可利用他获取其他应用数据,达到信息交互的效果

3.Content Provider共享数据过程(例子解释):

抗战时期的一个地下情报组织(我的APP),建立一个咖啡馆(Content Provider)向上级提供

情报(数据),上级(其他APP)需要情报的时候会派接头人(ContentResolver)给他暗号和

地址(URI),让他到咖啡馆来获取情报。

ps:上面有几个关键的名词ContentResolver 数据 URI他们的作用上面的例子应该能看出来(后面深入讲解)

4.Content Provider作用:

4.1 向其他app组件提供共享数据

4.2 存储及检索数据

ps:下面用一个例子带描述的形式学习Content Provider的创建管理,以及访问

5.Content Provider创建

5.1 创建Sqlite数据库(伙伴们不知道Sqlite没关系我们先用它讲解Content Provider的使用,后面再单独学习Sqlite)

5.1.1 创建数据库管理类MyDBOpenHelper继承SQLiteOpenHelper

package com.demo.contentproviderdemo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MyDBOpenHelper extends SQLiteOpenHelper {
/*
* 带参构造方法,供外部实例化MyDBOpenHelper
*/
public MyDBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}

/*
* 数据库创建时调用,做一些创建数据表和初始化工作(non-Javadoc)
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE user(_id integer primary key autoincrement, user_name varchar(20))");
Log.i("SYS", "create table user");
}

/*
* 数据库传入版本与传入的版本不同时执行
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS user");
onCreate(db);
}

}


5.2 实现ContentProvider类

ContentProvider类中需要继承实现了方法:

1)public boolean onCreate() (创建ContentProvider时调用)

2)public Cursor query(Uri, String[], String, String[], String) ( 查询指定URI的content provider 返回Cursor)

3)public Uri insert(Uri, ContentValues) (插入数据到指定Uri的ContentProvider)

4)public int update(Uri, ContentValues, String, String[]) (更新指定Uri的ContentProvider数据)

5)public int delete(Uri, String, String[]) (删除指定Uri的ContentProvider数据)

6)public String getType(Uri) (获得指定数据的MIME类型)

MyContentProvider 类实现:

package com.demo.contentproviderdemo;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;

/**
*
* @author Andy_lau
*
*/
public class MyContentProvider extends ContentProvider {
private MyDBOpenHelper dbOpenHelper;
// 无uri匹配时默认匹配码NO_MATCH
private static final UriMatcher MATCHER = new UriMatcher(
UriMatcher.NO_MATCH);
private static final int USERS = 1;
private static final int USER = 2;

// 静态代码块建立uri和匹配码的映射关系,方便后面根据不同uri进行不同操作
static {
MATCHER.addURI("com.demo.contentproviderdemo", "Users", USERS);
MATCHER.addURI("com.demo.contentproviderdemo", "Users/#", USER);
}

/*
* MyContentProvider创建时调用,做一些初始化方法
*/
@Override
public boolean onCreate() {
// 实例化数据库管理类MyDBOpenHelper
dbOpenHelper = new MyDBOpenHelper(this.getContext(), "user.db", null, 1);
return true;
}

/*
* 接收外部数据进行数据查询操作
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();

switch (MATCHER.match(uri)) {
case USERS:
cursor = db.query("user", projection, selection, selectionArgs,
null, null, sortOrder);
break;
case USER:
long user_id = ContentUris.parseId(uri);
String where = "_id =" + user_id;
where = selection + "and" + where;
cursor = db.query("user", projection, where, selectionArgs, null,
null, sortOrder);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return cursor;
}

/*
* 返回数据的MIME类型
*/
@Override
public String getType(Uri uri) {
switch (MATCHER.match(uri)) {
case USERS:
// 数据集的MIME类型字符串则应该以vnd.android.cursor.dir/开头
return "vnd.android.cursor.dir/Users";

case USER:
// 单一数据的MIME类型字符串应该以vnd.android.cursor.item/开头
return "vnd.android.cursor.item/Users";

default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
}

/*
* 接收外部数据进行数据插入操作 Uri:外部传入的uri ContentValues:外部传入的数据集合
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
switch (MATCHER.match(uri)) {
case USERS:
// 特别说一下第二个参数是当name字段为空时,将自动插入一个NULL。
long rowid = db.insert("user", null, values);
Uri insertUri = ContentUris.withAppendedId(uri, rowid);// 得到代表新增记录的Uri
this.getContext().getContentResolver().notifyChange(uri, null);
return insertUri;

default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
}

/*
* 接收外部数据进行数据删除操作 selection:sql语句中where后面的参考字段 selectionArgs参考字段的值
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int count = 0;
switch (MATCHER.match(uri)) {
case USERS:
count = db.delete("user", selection, selectionArgs);
return count;

case USER:
// 从uri中获取id
long id = ContentUris.parseId(uri);
// 将id拼接到查询语句
String where = "_id=" + id;
if (selection != null && !"".equals(selection)) {
where = selection + " and " + where;
}
count = db.delete("user", where, selectionArgs);
return count;

default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
}

/*
* 接收外部数据进行数据更新操作
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
int count = 0;
switch (MATCHER.match(uri)) {
case USERS:
count = db.update("user", values, selection, selectionArgs);
return count;
case USER:
long id = ContentUris.parseId(uri);
String where = "_id=" + id;
if (selection != null && !"".equals(selection)) {
where = selection + " and " + where;
}
count = db.update("user", values, where, selectionArgs);
return count;
default:
throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
}
}

}


5.3 Manifest.xml注册ContentProvider

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.Andy.contentprovider"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- authorities与MyContentProvider中uriMatcher的第一个参数一致 -->
<provider
android:name=".MyContentProvider"
android:authorities="com.Andy.contentprovider" >
</provider>
</application>

</manifest>


6.Content Provider数据管理(数据增删改查)

Content Provider数据管理可用ContentProvider实现类;或者,通过数据库管理类SQLiteOpenHelper去实例化SQLiteDatabase操作类

从而实现数据管理(ContentProvider实现类上面已经实现,通过SQLiteDatabase管理的部分准备在sqlite那一部分去学习)

7.访问Content Provider获取数据

我们新建一个android工程去访问上面的ContentProvider

7.1 MainActivity.java(通过ContentResolver访问ContentProvider获取数据并绑定到UI展示)

package com.test.contentresvoler;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
private Button button;
private ListView listView;
final String uri = "content://com.demo.contentproviderdemo/Users";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 绑定button按钮
button = (Button) findViewById(R.id.button1);
// 绑定listview
listView = (ListView) findViewById(R.id.list);
// 设置button监听
button.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// 实例化ContentResolver ContentProvider管理类
ContentResolver contentResolver = getContentResolver();
// 根据String地址实例化Uri(访问ContentProvider路径)
Uri addUri = Uri
.parse("content://com.demo.contentproviderdemo/Users");
// 实例化数据封装类ContentValues
ContentValues values = new ContentValues();
// 放入数据
/*				values.put("_id", 3);
Log.i("_id", values.get("_id")+"");*/
values.put("user_name", "Andy");
// 通过管理类将数据与Uri整合
Uri uri = contentResolver.insert(addUri, values);
// toast提示信息
Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_LONG)
.show();
}
});
// 实例化ContentResolver ContentProvider管理类
ContentResolver contentResolver = getContentResolver();
// 根据String地址实例化Uri(访问ContentProvider路径)
Uri selectUri = Uri
.parse("content://com.demo.contentproviderdemo/Users");
// 通过通过管理类将数据与Uri整合contentResolver实例方法获取操作游标Cursor实例
Cursor cursor = contentResolver
.query(selectUri, null, null, null, null);

if (cursor == null) {
Log.i("report", "cursor is null");
} else {
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("_id"));
String user_name = cursor.getString(cursor.getColumnIndex("user_name"));
Log.i("id&name", id+"&"+user_name);
Toast.makeText(MainActivity.this,  id+"&"+user_name, Toast.LENGTH_LONG).show();
}
// 设置listview适配器,适配布局和数据
/*
* MainActivity.this
*/
ListAdapter listAdapter = new SimpleCursorAdapter(MainActivity.this, R.layout.list,
cursor, new String[] { "_id", "user_name" }, new int[] {
R.id.value_id, R.id.value_name },0);
listView.setAdapter(listAdapter);
}

// 设置listview item监听
listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// 通过位置获取listview显示内容,强制类型转换为Cursor
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// 通过cursor方法获取对应字段的值
int name = cursor.getColumnIndex("user_name");
// toast提示信息
Toast.makeText(MainActivity.this, name + "", Toast.LENGTH_LONG)
.show();
}
});

}

}
7.2 主UI布局activity_main.xml(展示查询结果)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.test.contentresvoler.MainActivity" >

<!-- text的内容尽量写到 strings.xml中,方便国际化 -->

<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_weight="1"
android:gravity="center"
android:text="编号" />

<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_weight="1"
android:gravity="center"
android:text="姓名" />
</LinearLayout>

<ListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ListView>

</LinearLayout>


7.3 ListView 自定义布局list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/value_id"
android:layout_gravity="center"
android:gravity="center"
/>

<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:id="@+id/value_name"
android:gravity="center"
/>

</LinearLayout>


8.UriMatcher & Uri

UriMatcher:我们先解释一下,UriMatcher用在哪儿,作用是啥?

UriMatcher用在Contentprovider实现类中,用来创建“暗号”接口路径和建立路径与code的匹配关系

//authority即是你注册provider的时候定义的路径(包名),path即访问路径可为table名,也可自定义

//code只是一个匹配码,一个Uri对应一个匹配码,用于后面对不同的uri执行不同的操作

uriMatcher.addURI(authority, path, code);

URI:上面提到过Uri相当于暗号和地址,什么意思呢,就是我定义一个Contentprovider开放一个“暗号”接口,好你ContentResolver

想要获得我提供的数据,你先根据地址找到我并告诉我暗号,如果暗号匹配我就把数据给你,这就是URI主要作用。

参考:/article/1358725.html

PS:学习大神们的,自己的思路总结,谢谢大神们的分享!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: