zoukankan      html  css  js  c++  java
  • Android ContentProvider数据共享

    一、构造一个自己的Provider实现App之间数据共享

     1、我们先来了解一下   Uri(统一资源定位符) 

    定义:每一个Content Provider使用一个公开的URI唯一标示其数据集,Android所提供的ContentProvider都存放android.provider包中  
    结构:分为A、B、C、D四个部分

    A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的; B:URI 的标识,唯一标识ContentProvider,外部调用者可以根据这个标识来找到它。为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般是定义该ContentProvider的包.类的名称 C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了; D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.gdnf.provider/tablename/#" #表示数据id。

    路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
    1、要操作person表中id为10的记录,可以构建这样的路径:/person/10
    2、要操作person表中id为10的记录的name字段, person/10/name
    3、要操作person表中的所有记录,可以构建这样的路径:/person
    4、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
    5、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri uri = Uri.parse("content://com.bing.provider.personprovider/person")

     2、UriMatcher

    UriMatcher主要用在ContentProvider中,用来构建URI匹配项和判断Uri的正确性,如在insert之前先判断用户传进来的Uri是否与UriMatcher定义的匹配。

     3、ContentUris

    Long id=ContentUris.parseId(uri);取出URI中传递的ID
    Uri uri=ContentUris.withAppendedId(uri,id);为Uri追加ID

       4、案例代码

    package com.example.provider;
    
    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.net.Uri;
    import android.support.annotation.Nullable;
    
    import com.example.dao.StuDao;
    
    /**
     * Created by Administrator on 2017/12/18.
     */
    
    public class StuProvider extends ContentProvider {
    
        //定义authorities--这是表示Uri的“B部分”,获取ContentProvider的包名
        private static final String  authorities="com.example.provider.stuprovider";
    
        //构建UriMatcher对象(用于管理和匹配Uri)
        private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
    
        //为每一个Uri定义一个编码
        //所有Stu的编码为1
        private static final int STUS=1;
        //一个Stu的编码为2
        private static final int STU=2;
        //根据姓名查找Stu的编码为3
        private static final int STU_NAME=3;
        //根据性别查找Stu的编码为4
        private static final int STU_SEX=4;
        //应用UriMatcher对象构建Uri匹配项
        static{
            //A部分默认为:content:。只需带入B、C、D的值
            matcher.addURI(authorities,"/stu",STUS);
            matcher.addURI(authorities,"/stu/#",STU);
            matcher.addURI(authorities,"/stu/#/name",STU_NAME);
            matcher.addURI(authorities,"/stu/#/sex",STU_SEX);
        }
    
        //声明上下文
        private Context context;
        @Override
        public boolean onCreate() {
            context=getContext();
            return false;
        }
    
        @Nullable
        @Override
        public String getType(Uri uri) {
            if(matcher.match(uri)==STUS){
                return "vnd.android.cursor.dir/stu";
            }else if(matcher.match(uri)==STU){
                return "vnd.android.cursor.item/stu";
            }
            return null;
        }
    
        @Nullable
        @Override
        public Uri insert(Uri uri, ContentValues contentValues) {
            if(matcher.match(uri)==STUS){
                long id=new StuDao(context).addStu(contentValues);//添加学生
                Uri newUri=ContentUris.withAppendedId(uri,id);
    
                //发生了数据变化,给出一个通知信号
                getContext().getContentResolver().notifyChange(uri,null);
                return newUri;
            }
            return null;
        }
    
        @Override
        public int delete(Uri uri, String s, String[] strings) {
            StuDao dao=new StuDao(context);
            switch (matcher.match(uri)){
                case STUS:
                    dao.delete("tb_stu",null,null);
                    break;
                case STU:
                    long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                    dao.delete("tb_stu","_id="+id,null);
                    break;
            }
            //发生了数据编号,给出一个通知信号
            getContext().getContentResolver().notifyChange(uri,null);
            return 0;
        }
    
        @Override
        public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
            StuDao dao=new StuDao(context);
            int i=-1;
            switch (matcher.match(uri)){
                case STUS:
                    i=dao.update("tb_stu",contentValues,s,strings);
                    break;
                case STU:
                    long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                    i=dao.update("tb_stu",contentValues,"_id="+id,null);
                    break;
            }
            //发生了数据编号,给出一个通知信号
            getContext().getContentResolver().notifyChange(uri,null);
            return 0;
        }
    
        @Nullable
        @Override
        public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
            StuDao dao=new StuDao(context);
            Cursor cursor=null;
            switch (matcher.match(uri)){
                case STUS:
                    cursor=dao.queryStu(strings,s,strings1,null,null,s1,null);
                    break;
                case STU:
                    long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                    cursor=dao.queryStu(strings,"_id="+id,null,null,null,s1,null);
                    break;
            }
            return cursor;
        }
    }

    二、在另一个程序中如何使用ContentResolver内容解析器进行数据操作

     1、ContentResolver操作ContentProvider中的数据

    当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用getContentResolver()方法获取ContentResolver对象

     2、监听ContentProvider中数据的变化

    如果ContentProvider的访问者需要监听ContentProvider中的数据变化,可以注册一个观察者getContentResolver().registerContentObserver(uri,bool,observer)

     3、数据提供者在数据发生改变时发出消息

    getContent().getContentResolver().notifyChange(uri,null)

     4、案例代码

    package com.example.android_contentprover_test;
    
    import android.app.Activity;
    import android.content.ContentProvider;
    import android.content.ContentResolver;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.database.ContentObserver;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        //定义一个ContentResolver内容解析器
        private ContentResolver resolver;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //获取系统的ContentResolver对象
            resolver=getContentResolver();
            //为resolver添加一个监听事件,监听数据是否发生变化
            Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
            resolver.registerContentObserver(uri,true,new StuObServer(handler));
        }
    
        //构建一个handler对象执行数据操作
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if(msg.what==1){
                    //为所欲为
                    findStuList(null);//执行查询
                }
            }
        };
    
        //构建一个观察者类
        private class StuObServer extends ContentObserver{
    
            private Handler handler;
            public StuObServer(Handler handler) {
                super(handler);
                this.handler=handler;
            }
            //当发生改变时
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                //监听到数据发生改变时,发出一个编号为1的消息
                handler.sendEmptyMessage(1);
            }
        }
    
        public void addStu(View view){
            //声明数据来源——路径
            Uri addUri=Uri.parse("content://com.example.provider.stuprovider/stu");
            //创建一个数据对象
            ContentValues values=new ContentValues();
            values.put("sname","Join");
            values.put("sage",21);
            values.put("ssex","男");
            //使用内容解析器执行添加(参数为:数据的来源,更改的数据)
            Uri newUri=resolver.insert(addUri,values);
            //通过解析器得到更改数据的ID
            long id= ContentUris.parseId(newUri);
            Toast.makeText(this, "添加学生成功,ID="+id, Toast.LENGTH_SHORT).show();
    
            //使用内容解析器调用查询方法,查询数据
            Cursor cursor=resolver.query(newUri,null,null,null,null);
            if(cursor.moveToNext()){
                int _id=cursor.getInt(cursor.getColumnIndex("_id"));
                String name=cursor.getString(cursor.getColumnIndex("sname"));
                Toast.makeText(this, "ID="+_id+",Name="+name, Toast.LENGTH_SHORT).show();
            }
            cursor.close();
        }
    
        public void findStuList(View view){
            Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
            Cursor cursor=resolver.query(uri,null,null,null,null);
            while(cursor.moveToNext()){
                int _id=cursor.getInt(cursor.getColumnIndex("_id"));
                String name=cursor.getString(cursor.getColumnIndex("sname"));
                Log.i("App1 StuList", "ID="+_id+",Name="+name);
            }
            cursor.close();
        }
    }
  • 相关阅读:
    页面抛出的"Unable to validate data"错误
    oracle的sqlnet.ora,tnsnames.ora,listener.ora三个配置文件 water
    Win7下完全卸载Oracle 11g water
    抛出多个异常 water
    【转】有关Oracle随机字符串的生成方法及具体应用 water
    【转】oracle 中随机取一条记录的两种方法 water
    【转】Oracle索引列NULL值引发执行计划该表的测试示例 water
    Oracle 取随机数 water
    dbms_output.put_line长度限制问题 water
    oracle 监听启动、停止、查看命令 water
  • 原文地址:https://www.cnblogs.com/QQ862668193/p/8057648.html
Copyright © 2011-2022 走看看