我正在为一家面包店制作一个电子商务应用程序(一个熟悉android的个人项目)。
我已经创建了两个数据库,一个数据库用于存储要注册的客户数据,另一个数据库用于存储当前有库存的所有商品,可以从listView进行订购,每个商品都包含一个“添加到购物车”按钮。
我已经为第一个数据库使用了内容提供程序,即customerRegistry.db。当我尝试显示可用项目的列表时,我需要访问第二个数据库并查询数据并将其显示在列表视图中正确吗?但是,第一个数据库中的ContentProvider试图搜索项目的URI并给出错误消息。
我不希望ContentProvider用于客户数据来搜索商品的URI,显然它找不到任何东西。如何阻止它发生?
该项目是我几个月前完成的Udacity课程项目的扩展。
这是用于存储客户数据的第一个数据库的代码
在一个新包中,我创建了以下类。
public final class customerContract {
public static final String CONTENT_AUTHORITY = "com.example.dell.nammabakery";
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final String PATH_DETAILS = "details";
private customerContract() {
}
public static final class customerDataEntry implements BaseColumns {
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_DETAILS);
public static final String CONTENT_LIST_TYPE =
ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_DETAILS;
public static final String CONTENT_ITEM_TYPE =
ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + PATH_DETAILS;
/**
* Name of database table for customer registry
*/
public final static String TABLE_NAME = "customerRegistry";
/**
* Unique ID number for the item (only for use in the database table).
* <p>
* Type: INTEGER
*/
public final static String _ID = BaseColumns._ID;
public final static String COLUMN_CUSTOMER_NAME = "name";
public final static String COLUMN_CUSTOMER_USERNAME = "username";
public final static String COLUMN_CUSTOMER_PASSWORD = "password";
public final static String COLUMN_CUSTOMER_EMAIL = "email";
public final static String COLUMN_CUSTOMER_ADDRESS = "address";
public final static String COLUMN_PHONE_NUMBER = "phoneNumber";
}
}
扩展SQLiteOpenHelper的类
public class customerDbHelper extends SQLiteOpenHelper {
public static final String LOG_TAG = customerDbHelper.class.getSimpleName();
/**
* Name of the database file
*/
private static final String DATABASE_NAME = "customerRegistory.db";
/**
* Database version. If you change the database schema, you must increment the database version.
*/
private static final int DATABASE_VERSION = 1;
public customerDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Create a String that contains the SQL statement to create the pets table
String SQL_CREATE_ITEMS_TABLE = "CREATE TABLE " + customerDataEntry.TABLE_NAME + " ("
+ customerDataEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ customerDataEntry.COLUMN_CUSTOMER_NAME + " TEXT NOT NULL, "
+ customerDataEntry.COLUMN_CUSTOMER_USERNAME + " TEXT NOT NULL, "
+ customerDataEntry.COLUMN_CUSTOMER_PASSWORD + " TEXT NOT NULL, "
+ customerDataEntry.COLUMN_CUSTOMER_EMAIL + " TEXT NOT NULL, "
+ customerDataEntry.COLUMN_CUSTOMER_ADDRESS + " TEXT NOT NULL, "
+ customerDataEntry.COLUMN_PHONE_NUMBER + " LONG NOT NULL);";
// Execute the SQL statement
db.execSQL(SQL_CREATE_ITEMS_TABLE);
}
/**
* This is called when the database needs to be upgraded.
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// The database is still at version 1, so there's nothing to do be done here.
}
扩展ContentProvider的类
public class customerProvider extends ContentProvider {
public static final String LOG_TAG = customerProvider.class.getSimpleName();
/**
* URI matcher code for the content URI for the customerRegistry table
*/
private static final int CUSTOMERS = 100;
/**
* URI matcher code for the content URI for a single customer in the registry table
*/
private static final int CUSTOMER_ID = 101;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(customerContract.CONTENT_AUTHORITY, customerContract.PATH_DETAILS, CUSTOMERS);
sUriMatcher.addURI(customerContract.CONTENT_AUTHORITY, customerContract.PATH_DETAILS + "/#", CUSTOMER_ID);
}
/**
* Database helper object
*/
private customerDbHelper mDbHelper;
@Override
public boolean onCreate() {
mDbHelper = new customerDbHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Get readable database
SQLiteDatabase database = mDbHelper.getReadableDatabase();
// This cursor will hold the result of the query
Cursor cursor;
// Figure out if the URI matcher can match the URI to a specific code
int match = sUriMatcher.match(uri);
switch (match) {
case CUSTOMERS:
cursor = database.query(customerDataEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
case CUSTOMER_ID:
selection = customerDataEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
cursor = database.query(customerDataEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
// Return the cursor
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
final int match = sUriMatcher.match(uri);
switch (match) {
case CUSTOMERS:
return insertItem(uri, contentValues);
default:
throw new IllegalArgumentException("Insertion is not supported for " + uri);
}
}
private Uri insertItem(Uri uri, ContentValues values) {
// Check that the name is not null
String name = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_NAME);
if (name == null) {
throw new IllegalArgumentException("Customer requires a name");
}
String username = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
if(username == null) {
throw new IllegalArgumentException("Customer requires a username");
}
String password = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_PASSWORD);
if(password == null) {
throw new IllegalArgumentException("password is required");
}
String email = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_EMAIL);
if (email == null) {
throw new IllegalArgumentException("Customer requires an emailID");
}
// Check that the gender is valid
String address = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_ADDRESS);
if (address == null) {
throw new IllegalArgumentException("Customer requires valid address");
}
// If the weight is provided, check that it's greater than or equal to 0 kg
int phoneNumber = values.getAsInteger(customerDataEntry.COLUMN_PHONE_NUMBER);
if (String.valueOf(phoneNumber).length() != 10) {
throw new IllegalArgumentException("Customer requires a valid phone number");
}
// Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
// Insert the new pet with the given values
long id = database.insert(customerDataEntry.TABLE_NAME, null, values);
// If the ID is -1, then the insertion failed. Log an error and return null.
if (id == -1) {
Log.e(LOG_TAG, "Failed to insert row for " + uri);
return null;
}
// Notify all listeners that the data has changed for the pet content URI
getContext().getContentResolver().notifyChange(uri, null);
// Return the new URI with the ID (of the newly inserted row) appended at the end
return ContentUris.withAppendedId(uri, id);
}
@Override
public int update(Uri uri, ContentValues contentValues, String selection,
String[] selectionArgs) {
final int match = sUriMatcher.match(uri);
switch (match) {
case CUSTOMERS:
return updateItem(uri, contentValues, selection, selectionArgs);
case CUSTOMER_ID:
// For the PET_ID code, extract out the ID from the URI,
// so we know which row to update. Selection will be "_id=?" and selection
// arguments will be a String array containing the actual ID.
selection = customerDataEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
return updateItem(uri, contentValues, selection, selectionArgs);
default:
throw new IllegalArgumentException("Update is not supported for " + uri);
}
}
private int updateItem(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// If the {@link ItemEntry#COLUMN_ITEM_NAME} key is present,
// check that the name value is not null.
if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_NAME)) {
String name = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_NAME);
if (name == null) {
throw new IllegalArgumentException("Customer requires a name");
}
}
if(values.containsKey(customerDataEntry.COLUMN_CUSTOMER_USERNAME)) {
String username = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
if (username == null) {
throw new IllegalArgumentException("Customer requires a username");
}
}
if(values.containsKey(customerDataEntry.COLUMN_CUSTOMER_PASSWORD)) {
String password = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_USERNAME);
if(password == null) {
throw new IllegalArgumentException("Password is required");
}
}
if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_EMAIL)) {
String email = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_EMAIL);
if (email == null) {
throw new IllegalArgumentException("Customer requires a valid email");
}
}
// check that the gender value is valid.
if (values.containsKey(customerDataEntry.COLUMN_CUSTOMER_ADDRESS)) {
String address = values.getAsString(customerDataEntry.COLUMN_CUSTOMER_ADDRESS);
if (address == null) {
throw new IllegalArgumentException("Customer requires valid address");
}
}
// check that the weight value is valid.
if (values.containsKey(customerDataEntry.COLUMN_PHONE_NUMBER)) {
// Check that the weight is greater than or equal to 0 kg
Integer phoneNumber = values.getAsInteger(customerDataEntry.COLUMN_PHONE_NUMBER);
if (phoneNumber == null || String.valueOf(phoneNumber).length() < 10) {
throw new IllegalArgumentException("Customer requires a valid phone number");
}
}
// If there are no values to update, then don't try to update the database
if (values.size() == 0) {
return 0;
}
// Otherwise, get writeable database to update the data
SQLiteDatabase database = mDbHelper.getWritableDatabase();
// Perform the update on the database and get the number of rows affected
int rowsUpdated = database.update(customerDataEntry.TABLE_NAME, values, selection, selectionArgs);
// If 1 or more rows were updated, then notify all listeners that the data at the
// given URI has changed
if (rowsUpdated != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
// Return the number of rows updated
return rowsUpdated;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
// Track the number of rows that were deleted
int rowsDeleted;
final int match = sUriMatcher.match(uri);
switch (match) {
case CUSTOMERS:
// Delete all rows that match the selection and selection args
rowsDeleted = database.delete(customerDataEntry.TABLE_NAME, selection, selectionArgs);
break;
case CUSTOMER_ID:
// Delete a single row given by the ID in the URI
selection = customerDataEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(customerDataEntry.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Deletion is not supported for " + uri);
}
// If 1 or more rows were deleted, then notify all listeners that the data at the
// given URI has changed
if (rowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
// Return the number of rows deleted
return rowsDeleted;
}
@Override
public String getType(Uri uri) {
final int match = sUriMatcher.match(uri);
switch (match) {
case CUSTOMERS:
return customerDataEntry.CONTENT_LIST_TYPE;
case CUSTOMER_ID:
return customerDataEntry.CONTENT_ITEM_TYPE;
default:
throw new IllegalStateException("Unknown URI " + uri + " with match " + match);
}
}
}
我为Items数据库创建了一个新程序包,该程序包与customerRegistry数据库类似。
在片段中,我试图提取项目数据库中的数据,并将其显示在这样的列表视图中
public class BreadFragment extends Fragment {
private ItemDbHelper dbHelper;
private Context context;
public BreadFragment() {
// Required empty public constructor
}
@Override
@TargetApi(16)
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.product_list, container, true);
dbHelper = new ItemDbHelper(getContext());
SQLiteDatabase db = dbHelper.getReadableDatabase();
String[] projection = {
_ID,
itemDataEntry.COLUMN_ITEM_NAME,
itemDataEntry.COLUMN_ITEM_DESCRIPTION,
itemDataEntry.COLUMN_ITEM_IMAGE,
itemDataEntry.COLUMN_ITEM_PRICE,
};
final ArrayList<Product> products = new ArrayList<Product>();
Cursor cursor = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 1",null, null, null ,null);
products.add(new Product(cursor.getString(1), cursor.getString(2), getImage(cursor.getBlob(3)), cursor.getString(4)));
Cursor cursor1 = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 2",null, null, null ,null);
products.add(new Product(cursor1.getString(1), cursor1.getString(2), getImage(cursor1.getBlob(3)), cursor1.getString(4)));
Cursor cursor2 = db.query(itemDataEntry.TABLE_NAME, projection, "_ID = 3",null, null, null ,null);
products.add(new Product(cursor2.getString(1), cursor2.getString(2), getImage(cursor2.getBlob(3)), cursor2.getString(4)));
ProductAdapter adapter = new ProductAdapter(getActivity(), products, R.color.category_cookie);
ListView listView = (ListView) rootView.findViewById(R.id.list);
listView.setAdapter(adapter);
cursor.close();
cursor1.close();
cursor2.close();
return rootView;
}
但是我从customerProvider(从内容提供商扩展到)中收到错误 像这样
IllegalArgumentException:无法查询未知的URI ......
该提供者仅用于检查和/或共享客户数据,而不用于项目数据。如何阻止它尝试在customerRegistry.db中查找项目详细信息?