【数据存储】SQLite数据库存储(8) 开发ContentProvider程序

下面首先要定义出表示mldn数据库的元数据类。

import android.net.Uri;
import android.provider.BaseColumns;

public interface MLDNDatabaseMetaData {
    /* 这个是外部访问的Authority,Content地址为:
        content//org.lxh.demo.membercontentprovider  */
    public static final String AUTHORITY =
                 "org.lxh.demo.membercontentprovider" ;
    // 数据库的名字 ("mldn"操作的数据库的名字)
    public static final String DATABASE_NAME = "mldn" ;
View Code

此时就表示出了MLDN数据库之中的所有元数据,下面肯定要在一个数据库中有多张表,那么现在使用的是member,所以继续在这个数据库里面建立一个member表的元数据。

对于所有表而言,肯定都有一个"_id"的属性,所以为了简化定义,Android中专门提供了一个BaseColumn接口。

 

import android.net.Uri;
import android.provider.BaseColumns;
public interface MLDNDatabaseMetaData {
    /* 这个是外部访问的Authority,Content地址为:
       content//org.lxh.demo.membercontentprovider */
    public static final String AUTHORITY =
            "org.lxh.demo.membercontentprovider" ;
    // 数据库的名字 ("mldn"操作的数据库的名字)
    public static final String DATABASE_NAME = "mldn" ;    
    // 数据库的版本
    public static final int VERSION = 1 ;    
    /** 表示member表的元数据定义,直接继承_ID和_COUNT静态常量 */
    public static interface MemberTableMetaData extends BaseColumns{
        // 表名称
        public static final String TABLE_NAME = "member" ;    
        // 外部程序访问本表的Uri地址,而且名称都统一设置为CONTENT_URI
        public static final Uri CONTENT_URI = Uri.parse("content://"
                + AUTHORITY + "/" + TABLE_NAME);
        // 得到member表中的全部记录
        public static final String CONTACT_LIST =
           "vnd.android.cursor.dir/vnd.mldncontentprovider.member";
        // 取得一个member的信息,相当于就是按照ID查询
        public static final String CONTACT_ITEM =
          "vnd.android.cursor.item/vnd.mldncontentprovider.member";
        /** 一下表示member.name/age/birthday字段名称 */
        public static final String MEMBER_NAME = "name" ;
        public static final String MEMBER_AGE = "age" ;
        public static final String MEMBER_BIRTHDAY = "birthday" ;
        // 排序操作
        public static final String SORT_ORDER = "_id DESC" ;
    }
}
View Code

 

既然要操作的是数据库,那么就首先需要定义一个SQLiteOpenHelper类的子类。

 

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabaseHelper extends SQLiteOpenHelper {
    public MyDatabaseHelper(Context context) {
        super(context, MLDNDatabaseMetaData.DATABASE_NAME, null,
                MLDNDatabaseMetaData.VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
      String sql = "CREATE TABLE "
        + MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME + " ( "
        + MLDNDatabaseMetaData.MemberTableMetaData._ID
        + "    INTEGER     PRIMARY KEY ,"
        + MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_NAME
        + "    VARCHAR(50)    NOT NULL ,"
        + MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_AGE
        + "    INTEGER    NOT NULL ,"
        + MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_BIRTHDAY
        + "    DATE    NOT NULL" + " )";
        db.execSQL(sql) ;
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, 
      int newVersion) {
        String sql = "DROP TABLE IF EXISTS " + 
            MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME ;
        db.execSQL(sql) ;
        this.onCreate(db) ;
    }
}
View Code

以后就通过这个类取得数据库的连接对象,一切都准备完成之后,那么下面就必须动手编写ContentProvider程序 ----- MemberContentProvider.java。(分段讲解)

// 地址转换
    private static UriMatcher uriMatcher = null ;    
    // 得到全部的数据
    private static final int GET_MEMBER_LIST = 1 ;
    // 取得一个数据
    private static final int GET_MEMBER_ITEM = 2 ;    
    // 数据库操作类对象
    private MyDatabaseHelper helper = null ;
    static {    // 静态代码块
      // 实例化对象
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH) ;    
      // 取得全部数据的匹配地址
      uriMatcher.addURI(MLDNDatabaseMetaData.AUTHORITY,
        MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
                GET_MEMBER_LIST);    
      // 取得一个数据的匹配地址
      uriMatcher.addURI(MLDNDatabaseMetaData.AUTHORITY,
        MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME+"/#",
                GET_MEMBER_ITEM);    
    }
View Code

这个部分就相当于为用户准备好了一个所有地址的匹配集合,以后只要有地址传入,与这种地址一匹配,就知道执行的是何种查询操作。

ContentProvider程序之中,也存在一个onCreate(),很明显,这个是进行初始化操作的。

// 数据库操作类对象
    private MyDatabaseHelper helper = null ;
    @Override
    public boolean onCreate() {
        this.helper = new MyDatabaseHelper(super.getContext()) ;
        return true;    // 操作成功了
    }
View Code

上段程序中,onCreate()为回调方法,在创建此类对象时调用,所以在此方法中的主要功能是实例化MyDatabaseHelper数据库的辅助操作类的对象。

@Override  // 取得数据的类型的
    public String getType(Uri uri) { 
        // 匹配传入进来的Uri的类型
        switch (uriMatcher.match(uri)) { 
        case GET_MEMBER_LIST:
    return MLDNDatabaseMetaData.MemberTableMetaData.CONTACT_LIST;
        case GET_MEMBER_ITEM:
    return MLDNDatabaseMetaData.MemberTableMetaData.CONTACT_ITEM;
        default:
            throw new UnsupportedOperationException("Not 
             Support Operation :" + uri);
        }
    }
View Code

getType()主要作用是返回操作地址的相应的MIME数据类型,这些数据类型都是通过MemberTableMetaData接口指定的常量,当传入Uri之后,首先通过match()找到指定Uri的位置,如果找到了,则返回之前通过addUri()设置的CODE:如果没找到,返回-1此时程序将手工抛出一个UnsupportedOperationException的异常。

@Override
    // content://org.lxh.demo.membercontentprovider/member
    public Uri insert(Uri uri, ContentValues values) {    
        // 以写方式打开数据库
        SQLiteDatabase db = this.helper.getWritableDatabase() ;
        // 取得增长后的数据ID
        long id = 0 ;    
        // 匹配传入的Uri
        switch(uriMatcher.match(uri)) {
        case GET_MEMBER_LIST :
id = db.insert(MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
              MLDNDatabaseMetaData.MemberTableMetaData._ID, values);
            // 取出地址
            String uriPath = uri.toString() ;
            // 建立新的Uri地址
            String path = uriPath + "/" + id ;
            // 返回一个member信息
            return Uri.parse(path) ;
        case GET_MEMBER_ITEM :
            return null ; 
        default:
            throw new UnsupportedOperationException(
                    "Not Support Operation :" + uri);
        }
    }
View Code

insert()为增加数据的标准方法,此方法返回的是一个Uri地址,在此Uri上要将用户插入后的IDUri的形式返回给客户端,在此方法中,使用UriMatcher类中的match()对传入的Uri进行判断,取出传入Uri对应的CODE

@Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // 以写方式打开数据库
        SQLiteDatabase db = this.helper.getWritableDatabase() ;
        int result = 0 ;    // 表示结果
        switch (uriMatcher.match(uri)) {
        // 更新全部数据
        case GET_MEMBER_LIST:
            result = db.update(
                MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
                values, null, null);
            break ;
        // 根据ID更新记录
        case GET_MEMBER_ITEM:
            // 找到里面的id
            long id = ContentUris.parseId(uri) ;    
            String where = "_id=" + id ;
            result = db.update(
                MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
                values, where, selectionArgs);
            break ;
        default:
            throw new UnsupportedOperationException(
                    "Not Support Operation :" + uri);
        }
        return result ; 
    }
@Override
    public int delete(Uri uri, String selection, 
      String[] selectionArgs)  {
        // 以写方式打开数据库
        SQLiteDatabase db = this.helper.getWritableDatabase() ;
        // 操作结果
        int result = 0    ;    
        switch (uriMatcher.match(uri)) {
        // 删除全部
        case GET_MEMBER_LIST:
            result = db.delete(
                MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
                selection, selectionArgs);    
            break ;
        // 找到一个数据的ID
        case GET_MEMBER_ITEM:
            long id = ContentUris.parseId(uri) ;    
            String where = "_id=" + id ;
            result = db.delete(
                MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
                where,selectionArgs);
            break ;
        default:
            throw new UnsupportedOperationException("
               Not Support Operation :" + uri);
        }
        return result;
    }
@Override
    public Cursor query(Uri uri, String[] projection, String
       selection,String[] selectionArgs, String sortOrder) {
        // 以写方式打开数据库
        SQLiteDatabase db = this.helper.getWritableDatabase() ;
        switch (uriMatcher.match(uri)) {
        case GET_MEMBER_LIST:
          return db.query(
           MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
           projection, selection, selectionArgs, null, null,
              sortOrder);
        case GET_MEMBER_ITEM:
            // 找到ID
            long id = ContentUris.parseId(uri) ;    
            String where = "_id=" + id ;
            return db.query(
             MLDNDatabaseMetaData.MemberTableMetaData.TABLE_NAME,
             projection, where, selectionArgs, null, null,sortOrder);
        default:
            throw new UnsupportedOperationException(
              "Not Support Operation :" + uri);
        }
    }
View Code

定义访问ContentProvider应用程序的布局文件 --- main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout 
        android:orientation="horizontal" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/insertBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="增加" />
        <Button
            android:id="@+id/updateBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="更新" />
        <Button
            android:id="@+id/deleteBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="删除" />
        <Button
            android:id="@+id/queryBut"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="查询" />
    </LinearLayout>
    <TextView
        android:id="@+id/mainInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <ListView
        android:id="@+id/memberList"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>
</LinearLayout>
View Code

定义数据列表显示的布局文件 --- member.xml

<?xml version="1.0" encoding="utf-8"?>
<TableLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TableRow>
        <TextView
            android:id="@+id/_id"
            android:layout_height="wrap_content"
            android:layout_width="30px" />
        <TextView
            android:id="@+id/name"
            android:layout_height="wrap_content"
            android:layout_width="100px" />
        <TextView
            android:id="@+id/age"
            android:layout_height="wrap_content"
            android:layout_width="30px" />
        <TextView
            android:id="@+id/birthday"
            android:layout_height="wrap_content"
            android:layout_width="100px" />
    </TableRow>
</TableLayout>
View Code

下面开始完成Activity程序的开发,分别调用ContentProvider类中定义的insert()update()delete()query()方法。 MyContentProviderDemo.java

 

package org.lxh.demo;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MyContentProviderDemo extends Activity {
    private Button insertBut = null ;    // 操作按钮
    private Button updateBut = null ;
    private Button deleteBut = null ;
    private Button queryBut = null ;
    private TextView mainInfo = null ; // 操作提示
    private ListView memberList = null ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.main);
        this.mainInfo = 
            (TextView) super.findViewById(R.id.mainInfo) ;     
        this.insertBut = 
            (Button) super.findViewById(R.id.insertBut) ;     
        this.updateBut = 
            (Button) super.findViewById(R.id.updateBut) ;     
        this.deleteBut = 
            (Button) super.findViewById(R.id.deleteBut) ;     
        this.queryBut = (Button) super.findViewById(R.id.queryBut) ;
        this.memberList = 
           (ListView) super.findViewById(R.id.memberList) ;     
        this.insertBut.setOnClickListener(
                           new InsertOnClickListener()) ;
        this.updateBut.setOnClickListener(
                           new UpdateOnClickListener()) ;
        this.deleteBut.setOnClickListener(
                           new DeleteOnClickListener()) ;
        this.queryBut.setOnClickListener(
                           new QueryOnClickListener()) ;
    }
private long testInsert(String name,int age,String birthday)
    {    
        // 取得ContentResolver对象
        ContentResolver contentResolver =
                            super.getContentResolver() ;    
        ContentValues values = new ContentValues() ;
        values.put(
       MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_NAME, name) ;
       values.put(
       MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_AGE, age) ;
        values.put(
       MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_BIRTHDAY, birthday) ;
        Uri resultUri = contentResolver.insert(
                MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI, values);
        // 解析出返回的id数据
        return ContentUris.parseId(resultUri) ;    
    }
    private long testDelete(String _id) {
        // 取得ContentResolver对象
        ContentResolver contentResolver =
                         super.getContentResolver() ;    
        long result = 0 ;
        if (_id == null || "".equals(_id)) {
            result = contentResolver.delete(
            MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI, 
            null,null);
        } else {
            result = contentResolver.delete(Uri.withAppendedPath(
            MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI,
             _id),null, null);
        }
        return result ;
    }
    private long testUpdate(String _id, String name, int age, 
     String birthday) { 
        long result = 0 ;    // 返回结果
        // 取得ContentResolver对象
        ContentResolver contentResolver =
                    super.getContentResolver() ;    
        ContentValues values = new ContentValues() ;
    values.put(MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_NAME, name) ;
    values.put(MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_AGE, age) ;
    values.put(MLDNDatabaseMetaData.MemberTableMetaData.MEMBER_BIRTHDAY, birthday) ;
        if(_id == null || "".equals(_id)) {    // 更新全部
            result = contentResolver.update(
            MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI, 
            values, null, null) ;
        } else {    // 按照id更新
            result = contentResolver.update(        Uri.withAppendedPath(
        MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI, _id),
        values, null, null);
        }
        return result ;    // 解析出返回的id数据
    }
    private Cursor testQuery(String id) {
        if(id == null || "".equals(id)) {    // 查询全部
            return super.getContentResolver().query(
            MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI,
             null,null, null,
            MLDNDatabaseMetaData.MemberTableMetaData.SORT_ORDER);
        } else {
            return super
                    .getContentResolver()
                    .query(Uri.withAppendedPath(
            MLDNDatabaseMetaData.MemberTableMetaData.CONTENT_URI,
                            id), null, null, null,
            MLDNDatabaseMetaData.MemberTableMetaData.SORT_ORDER);
        }
    }
View Code

 

由于客户端访问ContentProvider程序时都必须依靠ContentResolver类完成,所以先使用super.getContentResolver()取得了一个ContentResolver对象。

 

private class InsertOnClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            MyContentProviderDemo.this.mainInfo.setText(
              "执行的是增加操作...") ;
            // 接收返回的id数据
            long id = 0 ;    
            id = MyContentProviderDemo.this.testInsert("李兴华", 30,
                    // 增加数据
                    new SimpleDateFormat("yyyy-MM-dd")
                         .format(new Date()));    
            Toast.makeText(MyContentProviderDemo.this, 
                    "数据增加成功,ID为:" + id,
                    Toast.LENGTH_LONG).show();
        }
    }
    private class DeleteOnClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            MyContentProviderDemo.this.mainInfo.setText(
                "执行的是删除操作...") ;
            long result = 0 ;    // 接收返回的id数据
            // 更新数据
            result = MyContentProviderDemo.
                     this.testDelete(String.valueOf(4)); 
            Toast.makeText(MyContentProviderDemo.this, 
                    "删除了" + result + "条记录",
                    Toast.LENGTH_LONG).show();
        }
    }
    private class UpdateOnClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            MyContentProviderDemo.this.mainInfo.setText(
            "执行的是更新操作...") ;
            long result = 0 ;    // 接收返回的id数据
            // 更新数据
            result = MyContentProviderDemo.this.testUpdate(
                   "", "MLDN", 18,"1989-09-19"); 
            Toast.makeText(MyContentProviderDemo.this, 
                    "更新了" + result + "条记录",
                    Toast.LENGTH_LONG).show();
        }
    }
    private class QueryOnClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            MyContentProviderDemo.this.mainInfo.setText(
               "执行的是查询操作...") ;
            // 查询全部
            Cursor result =
                   MyContentProviderDemo.this.testQuery(null) ;
            // 结果集交给系统管理
            MyContentProviderDemo.this.startManagingCursor(result) ;    
            List<Map<String,Object>> members = 
                        new ArrayList<Map<String,Object>>() ;
            for (result.moveToFirst(); !result.isAfterLast(); result
                    .moveToNext()) {
                Map<String,Object> member = 
                          new HashMap<String,Object>() ;
                member.put("_id", result.getInt(0)) ;
                member.put("name", result.getString(1)) ;
                member.put("age", result.getInt(2)) ;
                member.put("birthday", result.getString(3)) ;
                members.add(member) ;
            }
            MyContentProviderDemo.this.memberList
                    .setAdapter(new SimpleAdapter(
                       MyContentProviderDemo.this,
                            members, R.layout.member, 
                             new String[] { "_id",
                                    "name", "age", "birthday" },
                              new int[] {
                                    R.id._id, R.id.name, R.id.age,
                                    R.id.birthday }));
            Toast.makeText(MyContentProviderDemo.this, "数据查询成功!",
                    Toast.LENGTH_LONG).show();
        }
    }
View Code

 

修改AndroidManifest.xml文件,配置ContentProvider应用

 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.lxh.demo" 
    android:versionCode="1" 
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />
    <application android:icon="@drawable/icon" 
                    android:label="@string/app_name">
        <provider
            android:name=".MemberContentProvider"
        android:authorities="org.lxh.demo.membercontentprovider" />
        <activity android:name=".MyContentProviderDemo"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category 
                   android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
View Code
原文地址:https://www.cnblogs.com/androidsj/p/3129601.html