• 【数据存储】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
  • 相关阅读:
    dp P1103 书本整理 洛谷
    dp 洛谷P1977 出租车拼车 线性dp
    Layui 在新标签中打开页面 / 模拟点击菜单
    布局 基础知识
    SpreadJS 生成报表
    ABP abp zreo 老版本 支持dotnet framework 4.0
    IIS 加载字体
    IIS 登录失败 该登陆名来自不受信任的域,不能与windows身份认证一起使用
    C# WebForm 打开默认页
    IIS 报错 Cannot open database "test4" requested by the login. The login failed. Login failed for user 'IIS APPPOOL est1'.
  • 原文地址:https://www.cnblogs.com/androidsj/p/3129601.html
Copyright © 2020-2023  润新知