ContentProvider作为Android的四大存储方式之一,有着广泛的应用性,它暴露了数据地址,可以让其他应用访问数据,可以用于存储图片、通讯录等信息,这篇博文将详细介绍ContentProvider、URIMatcher,LoaderManager,cursorAdapter的方法使用与介绍。使用ContentProvider的时候一定要注意在manifest清单文件中像Acticity文件一样,声明其属性。如图所示
此外因为我们是用loadermanager来加载数据,MainAcitivity类要实现LoaderCallback接口。按照惯例我们还是看下谷歌官方文档对contentprovider的解释,ContentProvider管理一个结构化的数据集。它封装了数据,并提供定义数据安全机制。ContentProvider的标准接口实现多线程机制来连接数据,一般是用loaderManager异步加载数据。当你想要访问数据在一个ContentProvider,我们使用ContentResolver对象在应用程序的上下文中作为沟通方法。ContentResolver用来解析请求码返还数据。
我们先看看一下本次介绍的工程的目录结构
MainActivity的代码
package com.example.f14_contentprovider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.app.LoaderManager; import android.app.LoaderManager.LoaderCallbacks; import android.content.ContentResolver; import android.content.ContentValues; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public class MainActivity extends Activity implements LoaderCallbacks<Cursor> { private Button button; private ListView listView; private LoaderManager loaderManager; private SimpleCursorAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) this.findViewById(R.id.button1); listView = (ListView) this.findViewById(R.id.listView1); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub ContentResolver resolver = getContentResolver(); Uri uri = Uri .parse("content://com.example.f14_contentprovider.PersonContentProvider/person"); ContentValues values = new ContentValues(); values.put("name", "jack"); values.put("address", "hangzhou"); resolver.insert(uri, values); loaderManager.restartLoader(1001, null, MainActivity.this); } }); loaderManager = getLoaderManager(); loaderManager.initLoader(1001, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { // TODO Auto-generated method stub /** * CursorLoader该类用于加载程序,查询ContentResolver并返回一个指针。这个类实现了装载机协议查询游标的标准方法, * 基于AsyncTaskLoader执行游标查询在一个后台线程,以便它不会阻止应用程序的UI。 */ CursorLoader loader = new CursorLoader(this); Uri uri = Uri .parse("content://com.example.f14_contentprovider.PersonContentProvider/person"); loader.setUri(uri); loader.setProjection(new String[] { "name", "address" }); return loader; } @SuppressWarnings("deprecation") @Override public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { // TODO Auto-generated method stub List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(); // 加载数据 while (arg1.moveToNext()) { HashMap<String, String> map = new HashMap<String, String>(); map.put("name", arg1.getString(arg1.getColumnIndex("name"))); map.put("address", arg1.getString(arg1.getColumnIndex("address"))); list.add(map); } adapter = new SimpleCursorAdapter(this, R.layout.item, arg1, new String[] { "name", "address" }, new int[] { R.id.textView1, R.id.textView2 }); listView.setAdapter(adapter); adapter.notifyDataSetChanged();// 若内容发生变化 触发该方法 } @Override public void onLoaderReset(Loader<Cursor> arg0) { // TODO Auto-generated method stub } }如上所示,在MainAcitivity主方法中,大家可以看到第40-47行代码中,通过内容提供者contentProvider插入数据的时候,是通过contentResolver进行连接,通过其insert方法提供插入指定的数据表和数据完成操作。操作完成后还需要调用loadermanager的restart方法更新一次UI。
package com.example.f14_contentprovider; import android.content.ContentProvider; import android.content.ContentResolver; 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; //要在manifest文件中注册provider public class PersonContentProvider extends ContentProvider { private MyOpenHelper helper; private static final UriMatcher matcher = new UriMatcher( UriMatcher.NO_MATCH);// 专门用来匹配URI的类 private static final int PERSONS = 1; private static final int PERSON = 2; private ContentResolver resolver; static { matcher.addURI("com.example.f14_contentprovider.PersonContentProvider", "person", PERSONS); matcher.addURI("com.example.f14_contentprovider.PersonContentProvider", "person/#", PERSON); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } // 当您需要匹配一个URI,调用匹配(URI),用来来建立一个查询,返回类型,插入或删除一行。 @Override public String getType(Uri arg0) { // TODO Auto-generated method stub int match = matcher.match(arg0); switch (match) { case PERSONS: return "vnd.android.cursor.dir/person"; case PERSON: return "vnd.android.cursor.item/person"; default: return null; } } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub SQLiteDatabase database = helper.getWritableDatabase(); long id = database.insert("person", null, values); Uri rUri = ContentUris.withAppendedId(uri, id); resolver.notifyChange(rUri, null); return rUri; } @Override public boolean onCreate() { // TODO Auto-generated method stub helper = new MyOpenHelper(getContext()); resolver = getContext().getContentResolver(); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub Cursor cursor = null; int flag = matcher.match(uri); SQLiteDatabase database = helper.getReadableDatabase(); switch (flag) { case PERSONS: cursor=database.query("person", null, null, null,null, null, null); break; case PERSON: long _id = ContentUris.parseId(uri); String where_value = " _id = " + _id; if (selection != null && !selection.equals("")) { where_value += selection; } cursor = database.query("person", projection, where_value, selectionArgs, null, null, sortOrder); break; default: break; } cursor.setNotificationUri(resolver, uri); return cursor; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { // TODO Auto-generated method stub return 0; } }
package com.example.f14_contentprovider; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class MyOpenHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 1; private static final String PERSON_TABLE_NAME = "person"; public MyOpenHelper(Context context) { super(context, PERSON_TABLE_NAME, null, DATABASE_VERSION); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL("create table " + PERSON_TABLE_NAME + "(_id integer primary key autoincrement,name varchar(64),address varchar(64))"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }