Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 554|回复: 0

[实例教程]再探Android多应用间数据共享机制,自定义ContentP

[复制链接]

该用户从未签到

发表于 2011-10-22 13:30:15 | 显示全部楼层 |阅读模式
Android中的ContentProvider是一种多应用数据共享的机制,任何时候同一Provider只会创建一次,是由系统进行初始化和管理的。本文中将通过实现一个简单通讯录的插入、删除、查询操作来让你了解ContentProvider机制极其自定义过程。读过本系列(读取手机中通讯录)(sqlite数据库操作)的读者可以发现,本文中实现的应用以这两篇内容为基础的。虽然,本文的MyContentProvider使用sqlite数据库进行持久化存储操作,包装后以ContentProvider机制供各app调用。但是,为理解ContentProvider,你必须有这样两个概念:一、它是一种可以跨应用共享数据的机制,正如本文开头所说。二、底层的存储在实现你的ContentProvider的时候可以自定义,即可以为数据库、也可以为文件,持久化或非持久化存储的其他形式。
程序截图如下:



类AcMain.java,为主Activity,用来实现应用的主界面控件和流程,代码:
//AcMain.java

package jtapp.contentproviders;



import android.app.Activity;

import android.content.ContentValues;

import android.database.Cursor;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;



public class AcMain extends Activity {

        private Button btInsertData = null;

        private Button btViewData = null;

        private Button btDelOne = null;

        private Button btClearAll = null;



        /** Called when the activity is first created. */

        @Override

        public void onCreate(Bundle savedInstanceState) {

                super.onCreate(savedInstanceState);

                setContentView(R.layout.main);



                btInsertData = (Button) findViewById(R.id.Button02);

                btInsertData.setOnClickListener(new ClickViewHandler());

                btViewData = (Button) findViewById(R.id.Button03);

                btViewData.setOnClickListener(new ClickViewHandler());

                btDelOne = (Button) findViewById(R.id.Button04);

                btDelOne.setOnClickListener(new ClickViewHandler());

                btClearAll = (Button) findViewById(R.id.Button05);

                btClearAll.setOnClickListener(new ClickViewHandler());

        }



        public class ClickViewHandler implements OnClickListener {

                @Override

                public void onClick(View v) {

                        if (v == btInsertData) {

                                InsertSomeRecords();

                        } else if (v == btViewData) {

                                ViewRecords();

                        } else if (v == btDelOne) {

                                DelOne();

                        } else if (v == btClearAll) {

                                DelAllPeople();

                        }

                }



                private void DelAllPeople() {

                        getContentResolver().delete(MyContacts.CONTENT_URI, null, null);

                }



                private void DelOne() {

                        int id;

                        Cursor c = getContentResolver().query(

                                        MyContacts.CONTENT_URI, null,

                                        null, null, MyContacts.NAME + " ASC");

                        if (c.moveToFirst()) {

                                int idxID = c.getColumnIndex(MyContacts._ID);

                                id = c.getInt(idxID);

                                getContentResolver().delete(MyContacts.CONTENT_URI,

                                                MyContacts._ID + " = " + id, null);

                        }

                }



                private void ViewRecords() {

                        // Make the query

                        Cursor c = managedQuery(MyContacts.CONTENT_URI, null, null, null,

                                        MyContacts._ID);

                        StringBuilder sbRecords = new StringBuilder("");

                        if (c.moveToFirst()) {

                                int idxID = c.getColumnIndex(MyContacts._ID);

                                int idxName = c.getColumnIndex(MyContacts.NAME);

                                int idxNumber = c.getColumnIndex(MyContacts.NUMBER1);

                                int idxEmail = c.getColumnIndex(MyContacts.EMAIL);

                                // Iterator the records

                                do {

                                        sbRecords.append(c.getInt(idxID));

                                        sbRecords.append(". ");

                                        sbRecords.append(c.getString(idxName));

                                        sbRecords.append(", ");

                                        sbRecords.append(c.getString(idxNumber));

                                        sbRecords.append(", ");

                                        sbRecords.append(c.getString(idxEmail));

                                        sbRecords.append("/n");

                                } while (c.moveToNext());

                        }

                        c.close();

                        // Refresh the content of TextView

                        ((TextView)(findViewById(

                                        R.id.TextView01))).setText(sbRecords);

                }



                private void InsertSomeRecords() {

                        ContentValues values = new ContentValues();

                        values.put(MyContacts.NAME, "朱元璋");

                        values.put(MyContacts.NUMBER1, "13965625585");

                        getContentResolver().insert(MyContacts.CONTENT_URI, values);

                        values.clear();

                        values.put(MyContacts.NAME, "玄烨");

                        values.put(MyContacts.EMAIL, "xueye1772@gmail.com");

                        getContentResolver().insert(MyContacts.CONTENT_URI, values);

                }

        }

}

代码中通过getContentResolver()调用contentprovider的delete、insert等操作,由系统根据uri决定调用哪个provider。
query查询除了用getContentResolver().query以外,还可以用activity.managedQuery调用,后者的Cursor的生命周期是由activity来自动管理,本文中的query就是属于这种情况。
主界面ui定义,main.xml,代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        androidrientation="vertical" android:layout_width="fill_parent"

        android:layout_height="fill_parent">

        <TextView android:layout_width="fill_parent"

                android:layout_height="wrap_content" android:text="@string/hello" />

        <TableRow android:id="@+id/TableRow01" android:layout_width="wrap_content"

                android:layout_height="wrap_content">

                <Button android:text="insert some records" android:id="@+id/Button02"

                        android:height="30px" android:layout_width="wrap_content"

                        android:layout_height="wrap_content" />

        </TableRow>

        <TableRow android:id="@+id/TableRow01" android:layout_width="wrap_content"

                android:layout_height="wrap_content">

                <Button android:text="delete one" android:id="@+id/Button04"

                        android:height="30px" android:layout_width="wrap_content"

                        android:layout_height="wrap_content" />

                <Button android:text="clear all" android:id="@+id/Button05"

                        android:height="30px" android:layout_width="wrap_content"

                        android:layout_height="wrap_content" />

        </TableRow>

        <Button android:text="view records" android:id="@+id/Button03"

                android:height="30px" android:layout_width="wrap_content"

                android:layout_height="wrap_content" android:layout_gravity="center" />

        <TextView android:text="..." android:id="@+id/TextView01"

                android:layout_width="wrap_content" android:layout_height="wrap_content" />

</LinearLayout>

MyContentProvider.java,代码:
package jtapp.contentproviders;

import android.content.ContentProvider;

import android.content.ContentUris;

import android.content.ContentValues;

import android.content.Context;

import android.database.Cursor;

import android.database.SQLException;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteQueryBuilder;

import android.database.sqlite.SQLiteStatement;

import android.net.Uri;

import android.text.TextUtils;

import android.util.Log;



public class MyContactsProvider extends ContentProvider {

        private static final String TAG = "MyContactsProvider";

        private static SQLiteDatabase mDB;



        private static void createTablesIfNotExists() {

                mDB.execSQL("CREATE TABLE IF NOT EXISTS "   

                + MyContacts.TB_NAME + " ("   

                + MyContacts._ID + " INTEGER PRIMARY KEY,"   

                + MyContacts.NAME + " VARCHAR,"  

                + MyContacts.NUMBER1 + " VARCHAR,"

                + MyContacts.EMAIL + " VARCHAR)");

        }



        @Override

        public int delete(Uri uri, String selection, String[] selectionArgs) {

                int count;

                switch (MyContacts.uriMatcher.match(uri)) {

                        case MyContacts.CONTACTS:

                                count = mDB.delete(MyContacts.TB_NAME,

                                                selection, selectionArgs);

                                break;

                        case MyContacts.CONTACT_ID:

                                String contactID = uri.getPathSegments().get(1);

                                count = mDB.delete(MyContacts.TB_NAME,

                                                MyContacts._ID + "=" + contactID, selectionArgs);

                                break;

                        default: throw new IllegalArgumentException(

                                        "Unsupported URI: " + uri);

                }

                return count;

        }



        @Override

        public String getType(Uri uri) {

                switch (MyContacts.uriMatcher.match(uri)) {

                        case MyContacts.CONTACTS:

                        return "vnd.android.cursor.dir/vnd.jtapp.contacts";

                        case MyContacts.CONTACT_ID:

                        return "vnd.android.cursor.item/vnd.ambow.contacts";

                        default:

                        throw new IllegalArgumentException("Unsupported URI: " + uri);

                }

        }



        @Override

        public Uri insert(Uri uri, ContentValues contentValues) {

                long rowId = mDB.insert(MyContacts.TB_NAME, null, contentValues);

                if (rowId > 0) {

                        Uri noteUri =

                                ContentUris.withAppendedId(MyContacts.CONTENT_URI,rowId);

                        getContext().getContentResolver().notifyChange(noteUri, null);

                        Log.d(TAG+"insert",noteUri.toString());

                        return noteUri;

                } else {

                    throw new SQLException("Failed to insert row into " + uri);

                }

        }



        @Override

        public boolean onCreate() {

                if (mDB == null) {

                        mDB = this.getContext().openOrCreateDatabase(MyContacts.TB_NAME,

                                        Context.MODE_PRIVATE, null);

                        createTablesIfNotExists();

                }

                return mDB != null;

        }



        @Override

        public Cursor query(Uri uri, String[] projection, String selection,

                        String[] selectionArgs, String sortOrder) {

                SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

                qb.setTables(MyContacts.TB_NAME);

               

                switch (MyContacts.uriMatcher.match(uri)) {

                        case MyContacts.CONTACT_ID:

                                qb.appendWhere(

                                                MyContacts._ID + "=" + uri.getPathSegments().get(1));

                                break;

                }

                String orderBy;

                if (TextUtils.isEmpty(sortOrder)) {

                        orderBy = MyContacts._ID;

                } else {

                        orderBy = sortOrder;

                }

                Cursor c = qb.query(mDB, projection, selection,

                                selectionArgs,null, null,orderBy);

                return c;        

        }



        @Override

        public int update(Uri uri, ContentValues contentValues, String selection,

                        String[] selectionArgs) {



                Log.d(TAG+"update",contentValues.toString());

                Log.d(TAG+"update",uri.toString());

               

                int count;               

                switch (MyContacts.uriMatcher.match(uri)) {

                        case MyContacts.CONTACTS:

                                Log.d(TAG+"update",MyContacts.CONTACTS+"");

                                count = mDB.update(

                                                MyContacts.TB_NAME, contentValues,

                                                selection, selectionArgs);

                                break;

                        case MyContacts.CONTACT_ID:

                                String contactID = uri.getPathSegments().get(1);

                                Log.d(TAG+"update",contactID+"");

                                count = mDB.update(MyContacts.TB_NAME,contentValues,

                                                MyContacts._ID + "=" + contactID,

                                                selectionArgs);

                                break;

                        default: throw new IllegalArgumentException(

                                        "Unsupported URI: " + uri);

                }

                return count;

        }

}
MyContentProvider扩展了android.content.ContentProvider类,数据层的操作就在该类中完成。sqlite、文件形式、内存对象,持久化或者非持久化数据存储都可以包装在此类中,本文中使用了sqlite数据库进行持久化存储。
getContext().getContentResolver().notifyChange可以通知观察者数据发生改变,这是处理多应用调用时数据同步的关键,本文并没有完整的展现。自定义的MyContentProvider.java中还实现了update方法,在AcMain中没有调用到,你可尝试一下如何实现。

与MyContentProvider有关的表mycontacts相对应类MyContacts.java,其中定义了唯一资源标示URI,表结构字段名等。任何contentprovider的调用都是通过系统来进行,因此,URI起到了定位资源和特定provider类的作用。
//MyContacts.java

package jtapp.contentproviders;



import android.content.UriMatcher;

import android.net.Uri;

import android.provider.BaseColumns;



public class MyContacts implements BaseColumns {

        public MyContacts(){

        }

        public static final String AUTHORITY =

                "jtapp.contentproviders.contacts";

        public static final String TB_NAME = "mycontacts";

        public static final Uri CONTENT_URI = Uri.parse(

                "content://" + AUTHORITY + "/" + TB_NAME);

        

        public static final int CONTACTS = 1;

        public static final int CONTACT_ID = 2;

        public static final UriMatcher uriMatcher;

        static{

                uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

                uriMatcher.addURI(AUTHORITY,"mycontacts",CONTACTS);

                uriMatcher.addURI(AUTHORITY,"mycontacts/#",CONTACT_ID);

        }

        

        public static final String _ID = "id";

        public static final String NAME = "name";

        public static final String NUMBER1 = "number1";

        public static final String EMAIL = "email";

}

应用配置文件AndroidManifest.xml 代码:
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

        package="jtapp.contentproviders" android:versionCode="1"

        android:versionName="1.0">

        <application android:icon="@drawable/icon" android:label="@string/app_name">

                <activity android:name=".AcMain" android:label="@string/app_name">

                        <intent-filter>

                                <action android:name="android.intent.action.MAIN" />

                                <category android:name="android.intent.category.LAUNCHER" />

                        </intent-filter>

                </activity>

                <provider android:authorities="jtapp.contentproviders.contacts"

                        android:name="MyContactsProvider"></provider>

        </application>

</manifest>
主要是里边插入了provider标签,向系统声明了自定义Provider的实现。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-6-15 23:28 , Processed in 0.408041 second(s), 50 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表