ContentProvider操作多张表

前一篇android 玩转ContentProvider之二--实现多个ContentProvider对多张表进行操作中提到的是多个ContentProvider处理,一个ContentProvider对应一张表,下面说一下一个ContentProvider操作多张表的用法。

因为只有一个ContentProvider,所以在ContentProvider中就要区别多张表,很明确一下子就找到解决问题的切入点。下面的方法就是这样做的。也就是说authority只有一个,但Content_uri还是要有多个,因为要对应多张表。下面看代码:

直接操作数据类DatabaseHelper跟前面是一样的

DatabaseHelper.java
[java] view plain copy
package com.jacp.database;

import android.content.Context;  
import android.database.sqlite.SQLiteDatabase;  
import android.database.sqlite.SQLiteOpenHelper;  
  
import com.jacp.demo.provider.Provider;  
  
/** 
 * 直接操作数据库类 
 * @author jacp 
 * 
 */  
public class DatabaseHelper extends SQLiteOpenHelper {  
    private static final String DATABASE_NAME = "jacp_demo.db";  
    private static final int DATABASE_VERSION = 1;  
  
    public DatabaseHelper(Context context) {  
        super(context, DATABASE_NAME, null, DATABASE_VERSION);  
    }  
  
@Override  
public void onCreate(SQLiteDatabase db) {  
    db.execSQL("CREATE TABLE " + Provider.ProgrammerColumns.TABLE_NAME + " ("  
            + Provider.ProgrammerColumns._ID + " INTEGER PRIMARY KEY,"  
            + Provider.ProgrammerColumns.NAME + " TEXT,"  
            + Provider.ProgrammerColumns.AGE + " INTEGER"  
            + ");");  
      
    db.execSQL("CREATE TABLE " + Provider.LeaderColumns.TABLE_NAME + " ("  
            + Provider.LeaderColumns._ID + " INTEGER PRIMARY KEY,"  
            + Provider.LeaderColumns.NAME + " TEXT,"  
            + Provider.LeaderColumns.TITLE + " TEXT,"  
            + Provider.LeaderColumns.LEVEL + " INTEGER"  
            + ");");  
}  

@Override  
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
    db.execSQL("DROP TABLE IF EXISTS " + Provider.ProgrammerColumns.TABLE_NAME);  
    db.execSQL("DROP TABLE IF EXISTS " + Provider.LeaderColumns.TABLE_NAME);  
    onCreate(db);  
}  

}
保存跟数据库及表有关的常量,里面只有一个authority:
Provider.java
[java] view plain copy
package com.jacp.demo.provider;

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

/**

  • 保存数据库中的常量
  • @author jacp

*/
public class Provider {

// 这里只有一个authority  
public static final String AUTHORITY = "com.jacp.provider.demo.common";  
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.jacp.demo";  

public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.jacp.demo";  

/** 
 * 保存programmer表中用到的常量 
 * @author jacp 
 * 
 */  
public static final class ProgrammerColumns implements BaseColumns {  
    // 注意这个地方和下面LeaderColumns类中CONTENT_URI一样,用的是同一个AUTHORITY  
    public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY +"/programmers");  
    public static final String TABLE_NAME = "programmer";  
    public static final String DEFAULT_SORT_ORDER = "age desc";  
      
    public static final String NAME = "name";  
    public static final String AGE = "age";  
      
}  
  
/** 
 * 保存leader表中用到的常量 
 * @author mayliang 
 * 
 */  
public static final class LeaderColumns implements BaseColumns {  
    public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY +"/leaders");  
    public static final String TABLE_NAME = "leader";  
    public static final String DEFAULT_SORT_ORDER = "level desc";  
      
    public static final String NAME = "name";  
    public static final String TITLE = "title";  
    public static final String LEVEL = "level";  
      
}  

}
对多张表数据进行增删改查操作的ContentProvider类:
CommonProvider.java

[java] view plain copy
package com.jacp.demo.provider;  
  
import java.util.HashMap;  
  
import android.content.ContentProvider;  
import android.content.ContentUris;  
import android.content.ContentValues;  
import android.content.UriMatcher;  
import android.database.Cursor;  
import android.database.SQLException;  
import android.database.sqlite.SQLiteDatabase;  
import android.database.sqlite.SQLiteQueryBuilder;  
import android.net.Uri;  
import android.text.TextUtils;  
  
import com.jacp.database.DatabaseHelper;  
  
/** 
 * 对programmer和leader表进行操作的ContentProvider 
 * @author jacp 
 * 
 */  
	public class CommonProvider extends ContentProvider {  
  
    private static HashMap<String, String> sprogrammersProjectionMap;  
  
private static final int PROGRAMMERS = 1;  
private static final int PROGRAMMERS_ID = 2;  
  
// 这里要增加匹配项  
private static final int LEADERS = 3;  
private static final int LEADERS_ID = 4;  

private static final UriMatcher sUriMatcher;  

private DatabaseHelper mOpenHelper;  

@Override  
public boolean onCreate() {  
    mOpenHelper = new DatabaseHelper(getContext());  
    return true;  
}  

@Override  
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  
        String sortOrder) {  
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();  
    String orderBy;  
    switch (sUriMatcher.match(uri)) { // 这里要对不同表的匹配结果做不同处理  
    case LEADERS:  
    case LEADERS_ID:  
        qb.setTables(Provider.LeaderColumns.TABLE_NAME);  
        // If no sort order is specified use the default  
        if (TextUtils.isEmpty(sortOrder)) {  
            orderBy = Provider.LeaderColumns.DEFAULT_SORT_ORDER;  
        } else {  
            orderBy = sortOrder;  
        }  
        break;  
    case PROGRAMMERS:  
    case PROGRAMMERS_ID:  
        qb.setTables(Provider.ProgrammerColumns.TABLE_NAME);  
        // If no sort order is specified use the default  
        if (TextUtils.isEmpty(sortOrder)) {  
            orderBy = Provider.ProgrammerColumns.DEFAULT_SORT_ORDER;  
        } else {  
            orderBy = sortOrder;  
        }  
        break;  
    default:  
        throw new IllegalArgumentException("Unknown URI " + uri);  
    }  

    switch (sUriMatcher.match(uri)) {  
    case LEADERS:  
    case PROGRAMMERS:  
        qb.setProjectionMap(sprogrammersProjectionMap);  
        break;  

    case PROGRAMMERS_ID:  
        qb.setProjectionMap(sprogrammersProjectionMap);  
        qb.appendWhere(Provider.ProgrammerColumns._ID + "=" + uri.getPathSegments().get(1));  
        break;  
          
    case LEADERS_ID:  
        qb.setProjectionMap(sprogrammersProjectionMap);  
        qb.appendWhere(Provider.LeaderColumns._ID + "=" + uri.getPathSegments().get(1));  
        break;  

    default:  
        throw new IllegalArgumentException("Unknown URI " + uri);  
    }  

    // Get the database and run the query  
    SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);  

    // Tell the cursor what uri to watch, so it knows when its source data changes  
    c.setNotificationUri(getContext().getContentResolver(), uri);  
    return c;  
}  

@Override  
public String getType(Uri uri) {  
    switch (sUriMatcher.match(uri)) { // 这里也要增加匹配项  
    case LEADERS:  
    case PROGRAMMERS:  
        return Provider.CONTENT_TYPE;  
    case PROGRAMMERS_ID:  
    case LEADERS_ID:  
        return Provider.CONTENT_ITEM_TYPE;  
    default:  
        throw new IllegalArgumentException("Unknown URI " + uri);  
    }  
}  

@Override  
public Uri insert(Uri uri, ContentValues initialValues) {  
    ContentValues values;  
    if (initialValues != null) {  
        values = new ContentValues(initialValues);  
    } else {  
        values = new ContentValues();  
    }  
      
    String tableName = "";  
    String nullColumn = "";  
    switch (sUriMatcher.match(uri)) { // 这里要对不同表的匹配结果做不同处理  
    case LEADERS:  
        tableName = Provider.LeaderColumns.TABLE_NAME;  
        nullColumn = Provider.LeaderColumns.NAME;  
        // Make sure that the fields are all set  
        if (values.containsKey(Provider.LeaderColumns.NAME) == false) {  
            values.put(Provider.LeaderColumns.NAME, "");  
        }  

        if (values.containsKey(Provider.LeaderColumns.TITLE) == false) {  
            values.put(Provider.LeaderColumns.TITLE, "");  
        }  
          
        if (values.containsKey(Provider.LeaderColumns.LEVEL) == false) {  
            values.put(Provider.LeaderColumns.LEVEL, 0);  
        }  
        break;  
    case PROGRAMMERS:  
        tableName = Provider.ProgrammerColumns.TABLE_NAME;  
        nullColumn = Provider.ProgrammerColumns.NAME;  
        // Make sure that the fields are all set  
        if (values.containsKey(Provider.ProgrammerColumns.NAME) == false) {  
            values.put(Provider.ProgrammerColumns.NAME, "");  
        }  

        if (values.containsKey(Provider.ProgrammerColumns.AGE) == false) {  
            values.put(Provider.ProgrammerColumns.AGE, 0);  
        }  
        break;  
    default:  
        // Validate the requested uri  
        throw new IllegalArgumentException("Unknown URI " + uri);  
              
    }  

    SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
    long rowId = db.insert(tableName, nullColumn, values);  
    if (rowId > 0) {  
        Uri noteUri = ContentUris.withAppendedId(uri, rowId);  
        getContext().getContentResolver().notifyChange(noteUri, null);  
        return noteUri;  
    }  

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

@Override  
public int delete(Uri uri, String where, String[] whereArgs) {  
    SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
    int count;  
    switch (sUriMatcher.match(uri)) { // 这里要对不同表的匹配结果做不同处理,注意下面用到的表名不要弄错了  
    case PROGRAMMERS:  
        count = db.delete(Provider.ProgrammerColumns.TABLE_NAME, where, whereArgs);  
        break;  

    case PROGRAMMERS_ID:  
        String programmerId = uri.getPathSegments().get(1);  
        count = db.delete(Provider.ProgrammerColumns.TABLE_NAME, Provider.ProgrammerColumns._ID + "=" + programmerId  
                + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
        break;  
          
    case LEADERS:  
        count = db.delete(Provider.LeaderColumns.TABLE_NAME, where, whereArgs);  
        break;  
          
    case LEADERS_ID:  
        String leaderId = uri.getPathSegments().get(1);  
        count = db.delete(Provider.LeaderColumns.TABLE_NAME, Provider.LeaderColumns._ID + "=" + leaderId  
                + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
        break;  

    default:  
        throw new IllegalArgumentException("Unknown URI " + uri);  
    }  

    getContext().getContentResolver().notifyChange(uri, null);  
    return count;  
}  

@Override  
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {  
    SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
    int count;  
    switch (sUriMatcher.match(uri)) { // 这里要对不同表的匹配结果做不同处理,注意下面用到的表名不要弄错了  
    case PROGRAMMERS:  
        count = db.update(Provider.ProgrammerColumns.TABLE_NAME, values, where, whereArgs);  
        break;  

    case PROGRAMMERS_ID:  
        String noteId = uri.getPathSegments().get(1);  
        count = db.update(Provider.ProgrammerColumns.TABLE_NAME, values, Provider.ProgrammerColumns._ID + "=" + noteId  
                + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
        break;  
    case LEADERS:  
        count = db.update(Provider.LeaderColumns.TABLE_NAME, values, where, whereArgs);  
        break;  
          
    case LEADERS_ID:  
        String leaderId = uri.getPathSegments().get(1);  
        count = db.update(Provider.LeaderColumns.TABLE_NAME, values, Provider.LeaderColumns._ID + "=" + leaderId  
                + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
        break;  

    default:  
        throw new IllegalArgumentException("Unknown URI " + uri);  
    }  

    getContext().getContentResolver().notifyChange(uri, null);  
    return count;  
}  

static {  
    sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
    sUriMatcher.addURI(Provider.AUTHORITY, "programmers", PROGRAMMERS);  
    sUriMatcher.addURI(Provider.AUTHORITY, "programmers/#", PROGRAMMERS_ID);  
      
    // 这里要增加另一张表的匹配项  
    sUriMatcher.addURI(Provider.AUTHORITY, "leaders", LEADERS);  
    sUriMatcher.addURI(Provider.AUTHORITY, "leaders/#", LEADERS_ID);  

    // 保存所有表用到的字段  
    sprogrammersProjectionMap = new HashMap<String, String>();  
    sprogrammersProjectionMap.put(Provider.ProgrammerColumns._ID, Provider.ProgrammerColumns._ID);  
    sprogrammersProjectionMap.put(Provider.ProgrammerColumns.NAME, Provider.ProgrammerColumns.NAME);  
    sprogrammersProjectionMap.put(Provider.ProgrammerColumns.AGE, Provider.ProgrammerColumns.AGE);  
      
    sprogrammersProjectionMap.put(Provider.ProgrammerColumns._ID, Provider.ProgrammerColumns._ID);  
    sprogrammersProjectionMap.put(Provider.ProgrammerColumns.NAME, Provider.ProgrammerColumns.NAME);  
    sprogrammersProjectionMap.put(Provider.LeaderColumns.TITLE, Provider.LeaderColumns.TITLE);  
    sprogrammersProjectionMap.put(Provider.LeaderColumns.LEVEL, Provider.LeaderColumns.LEVEL);  
}  

}
leader表对应的数据对象:
Leader.java

[java] view plain copy
package com.jacp.pojos;  
  
public class Leader {  
  
    public String name;  
    public String title;  
    public int level;  
}  

programmer表对应的数据对象:
Programmer.java

[java] view plain copy
package com.jacp.pojos;  
  
public class Programmer {  
  
    public String name;  
    public int age;  
}  

用Activity测试:

[java] view plain copy
package com.jacp.demo;  
  
import android.app.Activity;  
import android.content.ContentValues;  
import android.database.Cursor;  
import android.net.Uri;  
import android.os.Bundle;  
import android.text.TextUtils;  
import android.util.Log;  
  
import com.jacp.demo.provider.Provider;  
import com.jacp.pojos.Leader;  
import com.jacp.pojos.Programmer;  
  
public class ContentProviderDemoActivity extends Activity {  
      
    private static final String TAG = "ProviderActivity";  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        testLeader();  
        testProgrammer();  
    }  
      
    private void testProgrammer() {  
        Programmer p = new Programmer();  
        p.name = "jacp";  
        p.age = 99;  
        int id = insertProgrammer(p);  
        queryProgrammer(id);  
    }  
      
    private int insertProgrammer(Programmer programmer) {  
        ContentValues values = new ContentValues();  
        values.put(Provider.ProgrammerColumns.NAME, programmer.name);  
        values.put(Provider.ProgrammerColumns.AGE, programmer.age);  
        Uri uri = getContentResolver().insert(Provider.ProgrammerColumns.CONTENT_URI, values);  
        Log.i(TAG, "insert uri="+uri);  
        String lastPath = uri.getPathSegments().get(1);  
        if (TextUtils.isEmpty(lastPath)) {  
            Log.i(TAG, "insert failure!");  
        } else {  
            Log.i(TAG, "insert success! the id is " + lastPath);  
        }  
          
        return Integer.parseInt(lastPath);  
    }  
      
    private void queryProgrammer(int id) {  
        Cursor c = getContentResolver().query(Provider.ProgrammerColumns.CONTENT_URI, new String[] { Provider.ProgrammerColumns.NAME, Provider.ProgrammerColumns.AGE }, Provider.ProgrammerColumns._ID + "=?", new String[] { id + "" }, null);  
        if (c != null && c.moveToFirst()) {  
            Programmer p = new Programmer();  
            p.name = c.getString(c.getColumnIndexOrThrow(Provider.ProgrammerColumns.NAME));  
            p.age = c.getInt(c.getColumnIndexOrThrow(Provider.ProgrammerColumns.AGE));  
            c.close(); // 用完Cursor要释放资源,如果Cursor没有关闭系统会打出Error级别的Log  
            Log.i(TAG, "programmer.name="+p.name+"---programmer.age="+p.age);  
        } else {  
            Log.i(TAG, "query failure!");  
        }  
    }  
      
    private void testLeader() {  
        Leader leader = new Leader();  
        leader.name = "jacky";  
        leader.title = "CTO";  
        leader.level = 30;  
        int id = insertLeader(leader);  
        queryLeader(id);  
    }  
      
    private int insertLeader(Leader leader) {  
        ContentValues values = new ContentValues();  
        values.put(Provider.LeaderColumns.NAME, leader.name);  
        values.put(Provider.LeaderColumns.TITLE, leader.title);  
        values.put(Provider.LeaderColumns.LEVEL, leader.level);  
        Uri uri = getContentResolver().insert(Provider.LeaderColumns.CONTENT_URI, values);  
        Log.i(TAG, "insert uri="+uri);  
        String lastPath = uri.getLastPathSegment();  
        if (TextUtils.isEmpty(lastPath)) {  
            Log.i(TAG, "insert failure!");  
        } else {  
            Log.i(TAG, "insert success! the id is " + lastPath);  
        }  
          
        return Integer.parseInt(lastPath);  
    }  
      
    private void queryLeader(int id) {  
        Cursor c = getContentResolver().query(Provider.LeaderColumns.CONTENT_URI, new String[] { Provider.LeaderColumns.NAME, Provider.LeaderColumns.TITLE, Provider.LeaderColumns.LEVEL }, Provider.LeaderColumns._ID + "=?", new String[] { id + "" }, null);  
        if (c != null && c.moveToFirst()) {  
            Leader leader = new Leader();  
            leader.name = c.getString(c.getColumnIndexOrThrow(Provider.LeaderColumns.NAME));  
            leader.title = c.getString(c.getColumnIndexOrThrow(Provider.LeaderColumns.TITLE));  
            leader.level = c.getInt(c.getColumnIndexOrThrow(Provider.LeaderColumns.LEVEL));  
            Log.i(TAG, "leader.name="+leader.name+"---leader.title="+leader.title+"---leader.level="+leader.level);  
        } else {  
            Log.i(TAG, "query failure!");  
        }  
    }  

}
Manifest.xml文件中的配置:

[java] view plain copy
<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="com.jacp.demo"  
    android:versionCode="1"  
    android:versionName="1.0" >  
  
    <uses-sdk android:minSdkVersion="8" />  
  
    <application  
        android:icon="@drawable/ic_launcher"  
        android:label="@string/app_name" >  
        <activity  
            android:label="@string/app_name"  
            android:name=".ContentProviderDemoActivity" >  
            <intent-filter >  
                <action android:name="android.intent.action.MAIN" />  
  
                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
          
        <!-- 这里只注册了一个ContentProvider,要注意的地方和前面一样 -->  
        <provider android:name=".provider.CommonProvider"  
            android:authorities="com.jacp.provider.demo.common" />  
          
    </application>  
到此为止ContentProvider用法总结基本结束,有人会问了,什么时候用多个?什么时候用一个?我给的答案是看个人习惯及自己的需求,如果觉得以后这张表会被删除,那么最好是分开写,写多个ContentProvider,这样容易区分。有人又会问用ContentProvider不就是多余的,项目里面的数据不会跟外部共享,所以不需要ContentProvider,直接操作数据库得了。也没错,用了ContentProvider基本上是公开了数据,但个人感觉用ContentProvider的好处是在项目架构上面降低了类与类之间的耦合性,直接用Content_uri就可以对表进行操作,其它不管系统是怎么调用的,感觉这一点还是比较好,所以推荐。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值