• SQLite数据库与Contentprovider(2)


    ContentProvider

    在创建ContentProvider时,需要首先使用数据库、文件系统或网络实现底层存储功能,

    然后在继承ContentProvider的类中实现基本数据操作的接口函数,包括添加、删除、查找和更新等功能。

    调用者不能够直接调用ContentProvider的接口函数,而需要使用ContentResolver对象,

    通过URI间接调用ContentProvider。下图是ContentProvider调用关系。

    URI

    URI是通用资源标志符(Uniform Resource Identifier),用来定位任何远程或本地的可用资源

    ContentProvider使用的URI语法结构如下

    content://<authority>/<data_path>/<id>

    content://是通用前缀,表示该URI用于ContentProvider定位资源,无需修改。

    <authority>是授权者名称,用来确定具体由哪一个ContentProvider提供资源。因此,一般<authority>都由类的小写全称组成,以保证唯一性。

    <data_path>是数据路径,用来确定请求的是哪个数据集。

    例如:

    content://edu.hrbeu.peopleprovider/people/3

    可以省略id(/3)部分那么意味着整个数据。

    UriMatcher:

    在新构造的ContentProvider类中,通过构造一个UriMatcher,判断URI是单条数据还是多条数据。

    public void  addURI  (String authority, String path, int code)

    authority表示匹配的授权者名称

    path表示数据路径

    #可以代表任何数字 (content://<authority>/<data_path>/#

    code表示返回代码uriMatcher.match(uri))的返回值

    注册ContentProvider

    <provider android:name = ".PeopleProvider" android:authorities = "edu.hrbeu.peopleprovider"/> 

    实例:

    ContentProvider一般用于两个不同的进程之间的数据共享。

    1. 假设我们有一个新的工程(app),在此工程中创建一个people.db数据库,然后通过自定义了一个ContentProvider来共享数据库中的data。
    2. 我们可以通过注册provider时用到的authority在配合db path之类的来连接(content://<authority>/<data_path>/#)读取内容提供者(不同进程)的数据。

    首先是步骤1:

    *只要在AndroidManifast中注册provider就会执行对应的provider类。无需再MainActivity中调用或无需直接调用自定义的new provider。

    即系统自动会加载调用PeopleProvider类。

    <provider android:name = ".PeopleProvider" android:authorities = "edu.hrbeu.peopleprovider"/> 

    继承ContentProvider时代码如下:

    import android.content.*;
    import android.database.Cursor;
    import android.net.Uri;
     
    public class PeopleProvider extends ContentProvider{
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public String getType(Uri uri) {
            // TODO Auto-generated method stub
            return null;
        }
     
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO Auto-generated method stub
            return null;
        }
     
        @Override
        public boolean onCreate() {
            // TODO Auto-generated method stub
            return false;
        }
             @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            // TODO Auto-generated method stub
            return null;
        }
     
        @Override
        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            // TODO Auto-generated method stub
            return 0;
        }
    }

    类似数据库操作。可以这么理解,相对来说好理解。

    开始贴代码。。。

    package edu.hrbeu.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.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteDatabase.CursorFactory;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.database.sqlite.SQLiteQueryBuilder;
    import android.net.Uri;
    
    public class PeopleProvider extends ContentProvider {
        
        private static final String DB_NAME = "people.db";
        private static final String DB_TABLE = "peopleinfo";
        private static final int DB_VERSION = 1;
        
        private SQLiteDatabase db;
        private DBOpenHelper dbOpenHelper;
        
        private static final int MULTIPLE_PEOPLE = 1;
        private static final int SINGLE_PEOPLE = 2;
        private static final UriMatcher uriMatcher;
        static {
             uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
             uriMatcher.addURI(People.AUTHORITY, People.PATH_MULTIPLE, MULTIPLE_PEOPLE);
             uriMatcher.addURI(People.AUTHORITY, People.PATH_SINGLE, SINGLE_PEOPLE);
        }
    
        @Override
        public boolean onCreate() {
            // TODO Auto-generated method stub
            Context context = getContext();
            dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);
            db = dbOpenHelper.getWritableDatabase();
     
            if (db == null)
                return false;
            else 
                return true;    
    
        }
    
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            // TODO Auto-generated method stub
            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
            qb.setTables(DB_TABLE);
            switch(uriMatcher.match(uri)){
                case SINGLE_PEOPLE:
                    qb.appendWhere(People.KEY_ID + "=" + uri.getPathSegments().get(1));
                    break;
                default:
                    break;
            }
            Cursor cursor = qb.query(db, 
                    projection, 
                    selection, 
                    selectionArgs, 
                    null, 
                    null, 
                    sortOrder);
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
            return cursor;
    
        }
    
        @Override
        public String getType(Uri uri) {
            // TODO Auto-generated method stub
            switch(uriMatcher.match(uri)){
            case MULTIPLE_PEOPLE:
        return People.MINE_TYPE_MULTIPLE;
            case SINGLE_PEOPLE:
        return People.MINE_TYPE_SINGLE;
            default:
                    throw new IllegalArgumentException("Unkown uri:"+uri);
    }
    
        }
    
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO Auto-generated method stub
            long id = db.insert(DB_TABLE, null, values);
            if ( id > 0 ){
                Uri newUri = ContentUris.withAppendedId(People.CONTENT_URI, id);
                getContext().getContentResolver().notifyChange(newUri, null);
                return newUri;
            }
            throw new SQLException("Failed to insert row into " + uri);
    
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            int count = 0;
            switch(uriMatcher.match(uri)){
        case MULTIPLE_PEOPLE:
               count = db.delete(DB_TABLE, selection, selectionArgs);
               break;
                      case SINGLE_PEOPLE:
               String segment = uri.getPathSegments().get(1);
                             count = db.delete(DB_TABLE, People.KEY_ID + "=" + segment, selectionArgs);
               break;
       default:
               throw new IllegalArgumentException("Unsupported URI:" + uri);
    }
            getContext().getContentResolver().notifyChange(uri, null); 
            return count;
    
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            int count;
            switch(uriMatcher.match(uri)){
                     case MULTIPLE_PEOPLE:
                            count = db.update(DB_TABLE, values, selection, selectionArgs);
                            break;
                                         case SINGLE_PEOPLE:
                                                 String segment = uri.getPathSegments().get(1);
                            count = db.update(DB_TABLE, values, People.KEY_ID+"="+segment, selectionArgs);
                               break;
                                         default:
                throw new IllegalArgumentException("Unknow URI:" + uri);     
            }
            getContext().getContentResolver().notifyChange(uri, null);
            return count;
    
        }
        
          private static class DBOpenHelper extends SQLiteOpenHelper {
              
              public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {
                super(context, name, factory, version);
              }
              private static final String DB_CREATE = "create table " + 
                        DB_TABLE + " (" + People.KEY_ID + " integer primary key autoincrement, " +
                               People.KEY_NAME+ " text not null, " + People.KEY_AGE+ " integer," + People.KEY_HEIGHT + " float);";
            @Override
            public void onCreate(SQLiteDatabase _db) {
                // TODO Auto-generated method stub
                _db.execSQL(DB_CREATE);
            }
            @Override
            public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
                // TODO Auto-generated method stub
                _db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
                   onCreate(_db);
    
            }
    
          }
        
    }
    package edu.hrbeu.contentproviderdemo;
    import android.net.Uri;
     
    public class People{
        
        public static final String MIME_DIR_PREFIX = "vnd.android.cursor.dir";
        public static final String MIME_ITEM_PREFIX = "vnd.android.cursor.item";
        public static final String MINE_ITEM = "vnd.hrbeu.people";
        
        public static final String MINE_TYPE_SINGLE = MIME_ITEM_PREFIX + "/" + MINE_ITEM;
        public static final String MINE_TYPE_MULTIPLE = MIME_DIR_PREFIX + "/" + MINE_ITEM;
        public static final String AUTHORITY = "edu.hrbeu.peopleprovider";
        public static final String PATH_SINGLE = "people/#";
        public static final String PATH_MULTIPLE = "people";
        public static final String CONTENT_URI_STRING = "content://" + AUTHORITY + "/" + PATH_MULTIPLE;
        public static final Uri  CONTENT_URI = Uri.parse(CONTENT_URI_STRING); 
        
        public static final String KEY_ID = "_id";
        public static final String KEY_NAME = "name";
        public static final String KEY_AGE = "age";
        public static final String KEY_HEIGHT = "height";
    }

    MainActivity是空的。。。不贴出来了。

    运行结果没有任何内容,因为仅是添加了一个provider。

    看一下步骤2:

    在另一个App中调用此ContentProvider。

    无需再AndroidManifast中注册provider。

    只需对应步骤1中的People类里的静态变量是完全匹配的就是可以了。

    也就是说URI需要与我们自定义的ContentProvider保持一致。

    package edu.hrbeu.contentresolverdemo;
    import android.net.Uri;
     
    public class People{
        
        public static final String MIME_DIR_PREFIX = "vnd.android.cursor.dir";
        public static final String MIME_ITEM_PREFIX = "vnd.android.cursor.item";
        public static final String MINE_ITEM = "vnd.hrbeu.people";
        
        public static final String MINE_TYPE_SINGLE = MIME_ITEM_PREFIX + "/" + MINE_ITEM;
        public static final String MINE_TYPE_MULTIPLE = MIME_DIR_PREFIX + "/" + MINE_ITEM;
        public static final String AUTHORITY = "edu.hrbeu.peopleprovider";
        public static final String PATH_SINGLE = "people/#";
        public static final String PATH_MULTIPLE = "people";
        public static final String CONTENT_URI_STRING = "content://" + AUTHORITY + "/" + PATH_MULTIPLE;
        public static final Uri  CONTENT_URI = Uri.parse(CONTENT_URI_STRING); 
        
        public static final String KEY_ID = "_id";
        public static final String KEY_NAME = "name";
        public static final String KEY_AGE = "age";
        public static final String KEY_HEIGHT = "height";
    }

    操作Contentpriver提供的数据我们需要用到ContentResolver:

    package edu.hrbeu.contentresolverdemo;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    public class ContentResolverDemo extends Activity {
    
        private EditText nameText;
        private EditText ageText;
        private EditText heightText;
        private EditText idEntry;
    
        private TextView labelView;
        private TextView displayView;
    
        private ContentResolver resolver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_content_resolver_demo);
            nameText = (EditText) findViewById(R.id.name);
            ageText = (EditText) findViewById(R.id.age);
            heightText = (EditText) findViewById(R.id.hight);
            idEntry = (EditText) findViewById(R.id.id);
    
            labelView = (TextView) findViewById(R.id.label);
            displayView = (TextView) findViewById(R.id.display);
            Button addButton = (Button) findViewById(R.id.button1);
            Button queryAllButton = (Button) findViewById(R.id.button2);
            Button clearButton = (Button) findViewById(R.id.button3);
            Button queryButton = (Button) findViewById(R.id.button6);
            Button deleteButton = (Button) findViewById(R.id.button5);
            Button updateButton = (Button) findViewById(R.id.button7);
    
            resolver = this.getContentResolver();
            addButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    ContentValues values = new ContentValues();
    
                    values.put(People.KEY_NAME, nameText.getText().toString());
                    values.put(People.KEY_AGE,
                            Integer.parseInt(ageText.getText().toString()));
                    values.put(People.KEY_HEIGHT,
                            Float.parseFloat(heightText.getText().toString()));
    
                    Uri newUri = resolver.insert(People.CONTENT_URI, values);
                    labelView.setText("添加成功,URI:" + newUri);
    
                }
            });
            queryAllButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Cursor cursor = resolver.query(People.CONTENT_URI,
                            new String[] { People.KEY_ID, People.KEY_NAME,
                                    People.KEY_AGE, People.KEY_HEIGHT }, null,
                            null, null);
                    if (cursor == null) {
                        labelView.setText("数据库中没有数据");
                        return;
                    }
                    labelView.setText("数据库:" + String.valueOf(cursor.getCount())
                            + "条记录");
    
                    String msg = "";
                    if (cursor.moveToFirst()) {
                        do {
                            msg += "ID:"
                                    + cursor.getInt(cursor
                                            .getColumnIndex(People.KEY_ID)) + ",";
                            msg += "姓名:"
                                    + cursor.getString(cursor
                                            .getColumnIndex(People.KEY_NAME)) + ",";
                            msg += "年龄:"
                                    + cursor.getInt(cursor
                                            .getColumnIndex(People.KEY_AGE)) + ", ";
                            msg += "身高:"
                                    + cursor.getFloat(cursor
                                            .getColumnIndex(People.KEY_HEIGHT))
                                    + "
    ";
                        } while (cursor.moveToNext());
                    }
    
                    displayView.setText(msg);
    
                }
            });
    
            clearButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    displayView.setText("");
                }
            });
    
            queryButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/"
                            + idEntry.getText().toString());
                    Cursor cursor = resolver.query(uri, new String[] {
                            People.KEY_ID, People.KEY_NAME, People.KEY_AGE,
                            People.KEY_HEIGHT }, null, null, null);
                    if (cursor == null) {
                        labelView.setText("数据库中没有数据");
                        return;
                    }
    
                    String msg = "";
                    if (cursor.moveToFirst()) {
                        msg += "ID:"
                                + cursor.getInt(cursor
                                        .getColumnIndex(People.KEY_ID)) + ",";
                        msg += "姓名:"
                                + cursor.getString(cursor
                                        .getColumnIndex(People.KEY_NAME)) + ",";
                        msg += "年龄:"
                                + cursor.getInt(cursor
                                        .getColumnIndex(People.KEY_AGE)) + ", ";
                        msg += "身高:"
                                + cursor.getFloat(cursor
                                        .getColumnIndex(People.KEY_HEIGHT)) + "
    ";
                    }
    
                    labelView.setText("数据库:");
                    displayView.setText(msg);
    
                }
            });
            deleteButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/"
                            + idEntry.getText().toString());
                    int result = resolver.delete(uri, null, null);
                    String msg = "删除ID为" + idEntry.getText().toString() + "的数据"
                            + (result > 0 ? "成功" : "失败");
                    labelView.setText(msg);
                }
            });
    
            updateButton.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    ContentValues values = new ContentValues();
                    values.put(People.KEY_NAME, nameText.getText().toString());
                    values.put(People.KEY_AGE,
                            Integer.parseInt(ageText.getText().toString()));
                    values.put(People.KEY_HEIGHT,
                            Float.parseFloat(heightText.getText().toString()));
    
                    Uri uri = Uri.parse(People.CONTENT_URI_STRING + "/"
                            + idEntry.getText().toString());
                    int result = resolver.update(uri, values, null, null);
    
                    String msg = "更新ID为" + idEntry.getText().toString() + "的数据"
                            + (result > 0 ? "成功" : "失败");
                    labelView.setText(msg);
    
                }
            });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.content_resolver_demo, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }

    事成相识的布局文件也附上:

    <RelativeLayout 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: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="edu.hrbeu.contentresolverdemo.ContentResolverDemo" >
    
        <TextView android:id="@+id/Username" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:text="用户名:">
        </TextView>
    
        <EditText
            android:id="@+id/name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/Username" >
    
        </EditText>
    
        <TextView android:id="@+id/Userage" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/name"
            android:text="年龄:">
        </TextView>
        <EditText android:id="@+id/age" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/Userage">
        </EditText>
        
         <TextView android:id="@+id/Userhight" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/age"
            android:text="身高:">
        </TextView>
        <EditText android:id="@+id/hight" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/Userhight">
        </EditText>
    
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/button1"
            android:layout_alignBottom="@+id/button1"
            android:layout_centerHorizontal="true"
            android:text="全部显示" />
    
        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/button2"
            android:layout_alignBottom="@+id/button2"
            android:layout_alignRight="@+id/hight"
            android:text="清除显示" />
        
        <TextView android:id="@+id/Userid" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/button1"
            android:text="ID:">
        </TextView>
        <EditText android:id="@+id/id" 
            android:layout_height="wrap_content" 
            android:layout_width="fill_parent" 
            android:layout_below="@id/Userid">
        </EditText>
    
        <Button
            android:id="@+id/button6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/button5"
            android:layout_alignBottom="@+id/button5"
            android:layout_alignLeft="@+id/button2"
            android:text="ID查询" />
    
        <Button
            android:id="@+id/button7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/button6"
            android:layout_alignBottom="@+id/button6"
            android:layout_alignLeft="@+id/button3"
            android:text="ID更新" />
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/hight"
            android:text="添加数据" />
    
        <Button
            android:id="@+id/button5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/id"
            android:layout_below="@+id/id"
            android:text="ID删除" />
    
        <TextView
            android:id="@+id/display"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/label"
            android:layout_below="@+id/label"
            android:layout_marginTop="23dp" />
    
        <TextView
            android:id="@+id/label"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/button5"
            android:layout_below="@+id/button6"
            android:layout_marginTop="14dp" />
    
    </RelativeLayout>

    运行结果:

  • 相关阅读:
    【原】ListView的BeginUpdate()和EndUpdate()的用处
    【原】Telerik radwindow 在IE10下偶尔报 unable to get value of the property 'toLowerCase' 的解决办法
    【原】从头学习设计模式(一)——单例模式
    【原】从头学习设计模式(二)——简单工厂模式
    【原】通过JS打开IE新tab(非Window)的解决方案
    【原】高效GTD云工具 ——高效管理你的时间
    【原】安装Win7和Ubuntu双系统后,Win7耳机无声音的解决办法
    【原】从头学习设计模式(三)——工厂方法模式
    【原】备忘:Oracle 中创建存储过程及调用测试一例
    【转】DBA的性格
  • 原文地址:https://www.cnblogs.com/hongguang-kim/p/5631952.html
Copyright © 2020-2023  润新知