我正在创建一个库存应用程序。它有一个制作按钮,菜单按钮有两个项目。一切正常,但每当我试图通过菜单中的项目插入新产品时。它不会立即添加。< / p>
首先我必须从应用程序返回或杀死它,然后当我再次进入时,那里记录了具有虚拟值的新产品。我想解决当我添加新产品时立即添加的问题带有值的数据,我不必每次都返回看它插入。如果使用fab按钮添加新产品,我之前添加并使用插入项添加的数据也会被添加和显示。 我已经看到了通知uri,并且LOGCAT中没有显示错误
ProductProvider.java
package com.example.bahubali.inventoryapp.data;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
public class ProductProvider extends ContentProvider {
//Tag for the log messages
public static final String LOG_TAG = ProductProvider.class.getSimpleName();
//Database helper that will provide access to the database.
private ProductDbHelper mDbHelper;
/** URI matcher code for the content URI for the product table */
public static final int PRODUCTS = 100;
/** URI matcher code for the content URI for a single product in the pets table */
public static final int PRODUCT_ID = 101;
/** URI matcher object to match a context URI to a corresponding code.
* The input passed into the constructor represents the code to return for the root URI.
* It's common to use NO_MATCH as the input for this case.
*/
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// Static initializer. This is run the first time anything is called from this class.
static {
// The calls to addURI() go here, for all of the content URI patterns that the provider
// should recognize. All paths added to the UriMatcher have a corresponding code to return
// when a match is found.
sUriMatcher.addURI(ProductContract.CONTENT_AUTHORITY, ProductContract.PATH_PRODUCTS, PRODUCTS);
// The content URI of the form "content://com.example.android.pets/pets/#" will map to the
// integer code {@link #PETS_ID}. This URI is used to provide access to ONE single row
// of the pets table.
sUriMatcher.addURI(ProductContract.CONTENT_AUTHORITY, ProductContract.PATH_PRODUCTS + "/#", PRODUCT_ID);
}
/**
* Initialize the provider and the database helper object.
*/
@Override
public boolean onCreate()
{
/*
* Creates a new helper object. This method always returns quickly.
* until SQLiteOpenHelper.getWritableDatabase is called
*/
mDbHelper = new ProductDbHelper(getContext());
return true;
}
/*
*Perform the query to the given URI.Use the given projection,selection,selectionArgs, and sort
* order.
*/
@Override
public Cursor query(@NonNull 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 PRODUCTS:
// For the PRODUCTS code, query the pets table directly with the given
// projection, selection, selection arguments, and sort order. The cursor
// could contain multiple rows of the products table.
// Perform database query on pets
cursor = database.query(ProductContract.ProductEntry.TABLE_NAME,
projection,selection,selectionArgs,null,null,sortOrder);
break;
case PRODUCT_ID:
// For the PRODUCT_ID code, extract out the ID from the URI.
// For an example URI such as "content://com.example.android.products/products/3",
// the selection will be "_id=?" and the selection argument will be a
// String array containing the actual ID of 3 in this case.
//
// For every "?" in the selection, we need to have an element in the selection
// arguments that will fill in the "?". Since we have 1 question mark in the
// selection, we have 1 String in the selection arguments' String array.
selection = PRODUCT_ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
// This will perform a query on the products table where the _id equals 3 to return a
// Cursor containing that row of the table.
cursor = database.query(ProductContract.ProductEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
//Set notification URI to the cursor,
//So we know what content URI the cursor was created for.
cursor.setNotificationUri(getContext().getContentResolver(),uri);
//If the data at this URI changes, then we need to update the cursor.
return cursor;
}
/*
*Insert a new data into the provider with the given Constructor.
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri,
@Nullable ContentValues contentValues) {
final int match = sUriMatcher.match(uri);
switch (match){
case PRODUCTS:
return insertProduct(uri,contentValues);
default:
throw new IllegalArgumentException("Insertion is not supported for " +uri);
}
}
/*
Insert a product in the database with the given content values.Return the new content URI
for that specific row in the database.
*/
private Uri insertProduct(Uri uri, ContentValues contentValues){
//Check that the name is not null
String name = contentValues.getAsString(ProductContract.ProductEntry.COLUMN_PRODUCT_NAME);
if (name == null){
throw new IllegalArgumentException("Product requires a name");
}
//Check that the price is not null
Integer price = contentValues.getAsInteger(ProductContract.ProductEntry.COLUMN_PRODUCT_PRICE);
if (price != null && price < 0 ){
throw new IllegalArgumentException("Product requires valid price");
}
//Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
//Insert the new product with the given values
long id = database.insert(ProductContract.ProductEntry.TABLE_NAME,null,contentValues);
//If the Id is -1, then the insertion failed.Log on an error to return null
if (id == -1){
Log.e(LOG_TAG,"Failed to insert a row" + uri);
return null;
}
//Notify all listeners that the data has changed for the product content URI
getContext().getContentResolver().notifyChange(uri,null);
return ContentUris.withAppendedId(uri,id);
}
/*
*Updates the data at the given selection and the selection arguements, with the new content
* values.
*/
@Override
public int update(@NonNull Uri uri,
@Nullable ContentValues contentValues,
@Nullable String selection,
@Nullable String[] selectionArgs) {
final int match = sUriMatcher.match(uri);
switch (match) {
case PRODUCTS:
return updateProduct(uri, contentValues, selection, selectionArgs);
case PRODUCT_ID:
// For the PRODUCT_D 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 = ProductContract.ProductEntry._ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
return updateProduct(uri, contentValues, selection, selectionArgs);
default:
throw new IllegalArgumentException("Update is not supported for " + uri);
}
}
/**
* Update products in the database with the given content values. Apply the changes to the rows
* specified in the selection and selection arguments (which could be 0 or 1 or more pets).
* Return the number of rows that were successfully updated.
*/
private int updateProduct(Uri uri,ContentValues contentValues,String selection,String[] selectionArgs){
// If the {@link ProductEntry#COLUMN_PRODUCT_NAME} key is present,
// check that the name value is not null.
if (contentValues.containsKey(ProductContract.ProductEntry.COLUMN_PRODUCT_NAME)) {
String name = contentValues.getAsString(ProductContract.ProductEntry.COLUMN_PRODUCT_NAME);
if (name == null) {
throw new IllegalArgumentException("Product requires a name");
}
}
// If the {@link ProductEntry#COLUMN_PRODUCT_PRICE} key is present,
// check that the price value is valid.
if (contentValues.containsKey(ProductContract.ProductEntry.COLUMN_PRODUCT_PRICE)) {
// Check that the weight is greater than or equal to 0 kg
Integer price = contentValues.getAsInteger(ProductContract.ProductEntry.COLUMN_PRODUCT_PRICE);
if (price!= null && price < 0) {
throw new IllegalArgumentException("Product requires valid weight");
}
}
// If there are no values to update, then don't try to update the database
if (contentValues.size() == 0) {
return 0;
}
// Otherwise, get writeable database to update the data
SQLiteDatabase database = mDbHelper.getWritableDatabase();
//perform the update on the database and the get the number of rows affected
int rowsUpdated = database.update(ProductContract.ProductEntry.TABLE_NAME,contentValues,selection
,selectionArgs);
//If 1 or more rows were updated, then notify all the listeners that the data at the
//given URI has changed
if (rowsUpdated != 0){
getContext().getContentResolver().notifyChange(uri,null);
}
//Return the no. of rows updated
return rowsUpdated;
}
/*
*Delete the data at the given selection and selection arguements.
*/
@Override
public int delete(@NonNull Uri uri,
@Nullable String selection,
@Nullable String[] selectionArgs) {
// Get writeable database
SQLiteDatabase database = mDbHelper.getWritableDatabase();
//Track the no. of rows that were deleted
int rowsDeleted;
final int match = sUriMatcher.match(uri);
switch (match) {
case PRODUCTS:
// Delete all rows that match the selection and selection args
rowsDeleted = database.delete(ProductContract.ProductEntry.TABLE_NAME,selection,selectionArgs);
break;
case PRODUCT_ID:
// Delete a single row given by the ID in the URI
selection = ProductContract.ProductEntry._ID + "=?";
selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(ProductContract.ProductEntry.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
//given uri has changed
if (rowsDeleted != 0){
getContext().getContentResolver().notifyChange(uri,null);
}
return rowsDeleted;
}
/*
*Return the MIME type of data for the content URI.
*/
@Nullable
@Override
public String getType(@NonNull Uri uri) {
final int match = sUriMatcher.match(uri);
switch (match){
case PRODUCTS:
return ProductContract.ProductEntry.CONTENT_LIST_TYPE;
case PRODUCT_ID:
return ProductContract.ProductEntry.CONTENT_ITEM_TYPE;
default:
throw new IllegalStateException("UNKNOWN URI" + uri + " with match" + match);
}
}
}