Android – Comprobar si no nulo no funciona como se esperaba

Me encontré con un problema extraño en el que mi cheque no Null no funciona. Estoy tratando de verificar si los valores están vacíos y si aparece una advertencia que diga "Ingnetworkingiente requiere un nombre". No sé por qué pero no puedo entenderlo, lo que debería ser bastante simple.

Todavía soy nuevo en Kotlin, así que sospecho que mi process de pensamiento de Java a Kotlin es defectuoso aquí.

¡Cualquier ayuda y consejo sería muy apreciado!

La porción con la que estoy teniendo problemas:

// Check that the name is not null (if (values != null) values else throw KotlinNullPointerException()).getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) ?: throw IllegalArgumentException("Ingnetworkingient requires a name") 

La class completa. Tiendo a comentar la mierda de todo, así que espero que tenga sentido:

 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.util.Log import import kotlin.properties.Delegates class DbContentProvider : ContentProvider() { // Database helper object private var mDbHelper: DbHelper by Delegates.notNull() // Order the of ingnetworkingients in the list view private val ingnetworkingientSortBy = IngnetworkingientEntry.COLUMN_INGREDIENT_NAME override fun onCreate(): Boolean { mDbHelper = DbHelper(context) return true } override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? { // Get readable database val database: SQLiteDatabase = mDbHelper.readableDatabase // This cursor will hold the result of the query val cursor: Cursor // Figure out if the URI matcher can match the URI to a specific code val match = sUriMatcher.match(uri) when (match) { INGREDIENTS -> // For the INGREDIENTS code, query the ingnetworkingients table directly with the given // projection, selection, selection arguments, and sort order. The cursor // could contain multiple rows of the ingnetworkingients table. // Query is uri, projection, selection, selectionArgs, sortOrder and orderBy cursor = database.query(IngnetworkingientEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, ingnetworkingientSortBy) INGREDIENTS_ID -> { // For the INGREDIENTS_ID code, extract out the ID from the URI. // For an example URI such as "content://com.example.android.ingnetworkingients/ingnetworkingients/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. val mSelection = IngnetworkingientEntry._ID + "=?" val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString()) // This will perform a query on the ingnetworkingients table where the _id equals 3 to return a // Cursor containing that row of the table. // Query is uri, projection, selection, selectionArgs, sortOrder and orderBy cursor = database.query(IngnetworkingientEntry.TABLE_NAME, projection, mSelection, mSelectionArgs, null, null, ingnetworkingientSortBy) } else -> throw IllegalArgumentException("Cannot query unknown URI " + uri) } // Set notification URI on the Cursor, // so we know what content URI the Cursor was created for. // If the data at this URI changes, then we know we need to update the Cursor. cursor.setNotificationUri(context.contentResolver, uri) // Return the cursor return cursor } override fun insert(uri: Uri, contentValues: ContentValues?): Uri? { val match = sUriMatcher.match(uri) when (match) { INGREDIENTS -> return insertIngnetworkingient(uri, contentValues) else -> throw IllegalArgumentException("Insertion is not supported for " + uri) } } /** * Insert an ingnetworkingient into the database with the given content values. Return the new content URI * for that specific row in the database. */ private fun insertIngnetworkingient(uri: Uri, contentValues: ContentValues?): Uri? { // Check that the name is not null or empty val ingnetworkingientName = contentValues?.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) if (ingnetworkingientName == null || ingnetworkingientName.isEmpty()) { throw IllegalArgumentException("Ingnetworkingient requires valid category") } // Check that the category is valid val category = contentValues.getAsInteger(IngnetworkingientEntry.COLUMN_INGREDIENT_CATEGORY) if (category == null || !IngnetworkingientEntry.isValidCategory(category)) { throw IllegalArgumentException("Ingnetworkingient requires valid category") } // Check that the measurement is valid val measurement = contentValues.getAsInteger(IngnetworkingientEntry.COLUMN_INGREDIENT_MEASUREMENT) if (measurement == null || !IngnetworkingientEntry.isValidMeasurement(measurement)) { throw IllegalArgumentException("Ingnetworkingient requires valid measurement") } // No need to check the description, any value is valid (including null). // Get writable database val database = mDbHelper.writableDatabase // Insert the new ingnetworkingient with the given values val id = database.insert(IngnetworkingientEntry.TABLE_NAME, null, contentValues) // If the ID is -1, then the insertion failed. Log an error and return null. if (id == (-1).toLong()) { Log.e(LOG_TAG, "Failed to insert row for " + uri) return null } // Notify all listeners that the data has changed for the ingnetworkingient content URI context.contentResolver.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 fun update(uri: Uri, contentValues: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int { val match = sUriMatcher.match(uri) return when (match) { INGREDIENTS -> updateIngnetworkingient(uri, contentValues, selection, selectionArgs) INGREDIENTS_ID -> { // For the INGREDIENTS_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. val mSelection = IngnetworkingientEntry._ID + "=?" val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString()) updateIngnetworkingient(uri, contentValues, mSelection, mSelectionArgs) } else -> throw IllegalArgumentException("Update is not supported for " + uri) } } /** * Update ingnetworkingients in the database with the given content contentValues. Apply the changes to the rows * specified in the selection and selection arguments (which could be 0 or 1 or more ingnetworkingients). * Return the number of rows that were successfully updated. */ private fun updateIngnetworkingient(uri: Uri, contentValues: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int { // If the {@link IngnetworkingientEntry#COLUMN_INGREDIENT_NAME} key is present, // check that the name value is not null. if ((if (contentValues != null) contentValues else throw KotlinNullPointerException()).containsKey(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME)) { contentValues.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) ?: throw IllegalArgumentException("Ingnetworkingient requires a name") } // If the {@link IngnetworkingientEntry#COLUMN_INGREDIENT_CATEGORY} key is present, // check that the category value is valid. if (contentValues.containsKey(IngnetworkingientEntry.COLUMN_INGREDIENT_CATEGORY)) { val category = contentValues.getAsInteger(IngnetworkingientEntry.COLUMN_INGREDIENT_CATEGORY) if (category == null || !IngnetworkingientEntry.isValidCategory(category)) { throw IllegalArgumentException("Ingnetworkingient requires valid category") } } // If the {@link IngnetworkingientEntry#COLUMN_INGREDIENT_MEASUREMENT} key is present, // check that the measurement value is valid. if (contentValues.containsKey(IngnetworkingientEntry.COLUMN_INGREDIENT_MEASUREMENT)) { val measurement = contentValues.getAsInteger(IngnetworkingientEntry.COLUMN_INGREDIENT_MEASUREMENT) if (measurement == null || !IngnetworkingientEntry.isValidMeasurement(measurement)) { throw IllegalArgumentException("Ingnetworkingient requires valid measurement") } } // No need to check the description, any value is valid (including null). // If there are no contentValues to update, then don't try to update the database if (contentValues.size() == 0) { return 0 } // Otherwise, get writable database to update the data val database = mDbHelper.writableDatabase // Perform the update on the database and get the number of rows affected val rowsUpdated = database.update(IngnetworkingientEntry.TABLE_NAME, contentValues, 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) { context.contentResolver.notifyChange(uri, null) } // Return the number of rows updated return rowsUpdated } override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { // Get writable database val database = mDbHelper.writableDatabase // Track the number of rows that were deleted val rowsDeleted: Int val match = sUriMatcher.match(uri) rowsDeleted = when (match) { INGREDIENTS -> // Delete all rows that match the selection and selection args database.delete(IngnetworkingientEntry.TABLE_NAME, selection, selectionArgs) INGREDIENTS_ID -> { // Delete a single row given by the ID in the URI val mSelection = IngnetworkingientEntry._ID + "=?" val mSelectionArgs = arrayOf(ContentUris.parseId(uri).toString()) database.delete(IngnetworkingientEntry.TABLE_NAME, mSelection, mSelectionArgs) } else -> throw 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) { context.contentResolver.notifyChange(uri, null) } // Return the number of rows deleted return rowsDeleted } override fun getType(uri: Uri): String? { val match = sUriMatcher.match(uri) return when (match) { INGREDIENTS -> IngnetworkingientEntry.CONTENT_LIST_TYPE INGREDIENTS_ID -> IngnetworkingientEntry.CONTENT_ITEM_TYPE else -> throw IllegalStateException("Unknown URI $uri with match $match") } } companion object { /** Tag for the log messages */ val LOG_TAG: String? = ContentProvider::class.java.simpleName /** URI matcher code for the content URI for the ingnetworkingients table */ private val INGREDIENTS = 100 /** URI matcher code for the content URI for a single ingnetworkingient in the ingnetworkingients table */ private val INGREDIENTS_ID = 101 /** * UriMatcher object to match a content 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 val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH) // Static initializer. This is run the first time anything is called from this class. init { // 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. // The content URI of the form "content://com.example.android.ingnetworkingients/ingnetworkingients" will map to the // integer code {@link #INGREDIENTS}. This URI is used to provide access to MULTIPLE rows // of the ingnetworkingients table. sUriMatcher.addURI(DbContract.CONTENT_AUTHORITY, DbContract.PATH_INGREDIENTS, INGREDIENTS) // The content URI of the form "content://com.example.android.ingnetworkingients/ingnetworkingients/#" will map to the // integer code {@link #INGREDIENTS_ID}. This URI is used to provide access to ONE single row // of the ingnetworkingients table. // // In this case, the "#" wildcard is used where "#" can be substituted for an integer. // For example, "content://com.example.android.ingnetworkingients/ingnetworkingients/3" matches, but // "content://com.example.android.ingnetworkingients/ingnetworkingients" (without a number at the end) doesn't match. sUriMatcher.addURI(DbContract.CONTENT_AUTHORITY, DbContract.PATH_INGREDIENTS + "/#", INGREDIENTS_ID) } } } 

Actualicé mi método y ahora es nulo o está vacío. Sin embargo, obviamente bloqueará mi aplicación si alguien deja el campo de nombre en blanco. ¿Alguna idea sobre cómo puedo informar al usuario de que el campo de nombre debe estar poblado, no bloquear mi aplicación y evitar que se cree el ingnetworkingiente? ¡Gracias!

 // Check that the name is not null or empty val ingnetworkingientName = contentValues?.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) if (ingnetworkingientName == null || ingnetworkingientName.isEmpty()) { throw IllegalArgumentException("Ingnetworkingient requires valid category") } 

Otra versión que hice atrapa la exception y no bloquea la aplicación, pero aún permite que el usuario cree un ingnetworkingiente sin nombre. ¡Bah!

 // Check that the name EditText field is not null or empty val ingnetworkingientName = contentValues?.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) if (ingnetworkingientName == null || ingnetworkingientName.isEmpty()) { try { throw Exception ("Ingnetworkingient requires a name") } catch (exception: Exception) { System.out.println(exception) } } 

Solutions Collecting From Web of "Android – Comprobar si no nulo no funciona como se esperaba"

Puede omitir la instrucción if y hacer esto en su lugar

 values?.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME) ?: throw IllegalArgumentException("Ingnetworkingient requires a name") 

Su operador elvis no funciona porque su instrucción if nunca devuelve un valor nulo, es la cadena o un NPE.

En realidad puedes mejorar tu código usando let block. algo como esto.

 values?.let{ //logic here that uses value, refer to value as it } ?: IllegalArgumentException() 

Editar

 values?.let{ if(it.getAsString(IngnetworkingientEntry.COLUMN_INGREDIENT_NAME).isEmpty()) throw IllegalArgumentException() else // do your logic }