Java 无法从我的应用程序中的菜单项插入新产品

Java 无法从我的应用程序中的菜单项插入新产品,java,android,android-sqlite,android-contentprovider,Java,Android,Android Sqlite,Android Contentprovider,我正在创建一个库存应用程序。它有一个fab按钮和一个带有两个项目的菜单按钮。一切正常,但每当我试图通过菜单中的项目插入新产品时。它不会立即添加 首先,我必须从应用程序返回或终止它,然后当我再次输入时,带有虚拟值的新产品被记录在那里。我想解决的问题是,当我添加一个新产品时,它会立即添加带有值的数据,我不必每次都返回以查看它被插入。如果使用fab按钮添加一个新产品,也可以我先前使用插入项添加的数据正在添加和显示。 我已经看到了通知uri,在LOGCAT中没有显示错误 ProductProvider.

我正在创建一个库存应用程序。它有一个fab按钮和一个带有两个项目的菜单按钮。一切正常,但每当我试图通过菜单中的项目插入新产品时。它不会立即添加

首先,我必须从应用程序返回或终止它,然后当我再次输入时,带有虚拟值的新产品被记录在那里。我想解决的问题是,当我添加一个新产品时,它会立即添加带有值的数据,我不必每次都返回以查看它被插入。如果使用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);
        }
    }

 }
package com.example.bahubali.inventoryapp.data;
导入android.content.ContentProvider;
导入android.content.ContentUris;
导入android.content.ContentValues;
导入android.content.UriMatcher;
导入android.database.Cursor;
导入android.database.sqlite.SQLiteDatabase;
导入android.net.Uri;
导入android.support.annotation.NonNull;
导入android.support.annotation.Nullable;
导入android.util.Log;
公共类ProductProvider扩展了ContentProvider{
//日志消息的标记
公共静态最终字符串LOG_TAG=ProductProvider.class.getSimpleName();
//将提供对数据库的访问的数据库帮助程序。
私人产品助手;
/**产品表的内容URI的URI匹配器代码*/
公共静态最终整数产品=100;
/**pets表中单个产品的内容URI的URI匹配器代码*/
公共静态最终整数乘积_ID=101;
/**URI matcher对象将上下文URI与相应的代码相匹配。
*传递到构造函数中的输入表示要为根URI返回的代码。
*在这种情况下,通常使用NO_MATCH作为输入。
*/
私有静态最终UriMatcher sUriMatcher=新UriMatcher(UriMatcher.NO_匹配);
//静态初始值设定项。这是首次从此类调用任何内容时运行的。
静止的{
//对于提供者提供的所有内容URI模式,对addURI()的调用都在这里
//应该可以识别。添加到UriMatcher的所有路径都有相应的代码要返回
//当找到匹配项时。
addURI(ProductContract.CONTENT\u AUTHORITY,ProductContract.PATH\u PRODUCTS,PRODUCTS);
//表单的内容URI“content://com.example.android.pets/pets/#“将映射到
//整数代码{@link#PETS_ID}。此URI用于提供对一行的访问
//在宠物桌上。
addURI(ProductContract.CONTENT_AUTHORITY,ProductContract.PATH_PRODUCTS+“/#”,PRODUCT_ID);
}
/**
*初始化提供程序和数据库帮助程序对象。
*/
@凌驾
公共布尔onCreate()
{
/*
*创建新的帮助对象。此方法总是快速返回。
*直到调用SQLiteOpenHelper.getWritableDatabase
*/
mDbHelper=newproductdbhelper(getContext());
返回true;
}
/*
*对给定的URI执行查询。使用给定的投影、选择、选择和排序
*秩序。
*/
@凌驾
公共游标查询(@NonNull Uri、字符串[]投影、字符串选择、字符串[]selectionArgs、,
字符串排序器){
//获取可读数据库
SQLiteDatabase=mDbHelper.getReadableDatabase();
//此光标将保存查询结果
光标;
//确定URI匹配器是否可以将URI与特定代码匹配
int match=sUriMatcher.match(uri);
开关(匹配){
案例产品:
//对于产品代码,使用给定的
//投影、选择、选择参数和排序顺序。光标
//可以包含products表的多行。
//对pets执行数据库查询
游标=database.query(ProductContract.ProductEntry.TABLE_NAME,
投影、选择、选择、空、空、排序器);
打破
案例产品编号:
//对于产品ID代码,从URI中提取ID。
//例如,URI为“content://com.example.android.products/products/3",
//选择将是“_id=?”,选择参数将是
//在本例中,包含实际ID为3的字符串数组。
//
//对于选择中的每个“?”,我们需要在选择中有一个元素
//将填充“?”的参数。因为在
//选择,在选择参数的字符串数组中有1个字符串。
选择=产品标识+“=?”;
selectionArgs=newstring[]{String.valueOf(ContentUris.parseId(uri))};
//这将对products表执行查询,其中_id等于3以返回
//包含表中该行的游标。
游标=database.query(ProductContract.ProductEntry.TABLE_NAME,
投影,
选择,
精选,
无效的
无效的
分拣机);
打破
违约:
抛出新的IllegalArgumentException(“无法查询未知URI”+u