【问题标题】:Android - adding validation to input fieldsAndroid - 向输入字段添加验证
【发布时间】:2017-06-19 21:07:05
【问题描述】:

我正在制作一个 Android 应用程序,它使用 sqlite database 来存储应用程序数据,activity 类来编辑/插入数据,DbHelper 来管理数据库的创建和版本,以及 content provider管理对数据库的访问。

我已经设法从数据库中获取要查询、插入、删除和编辑的数据。但是,我不太确定如何向用户添加视觉反馈。我尝试在我放置 IllegalArgumentException 的位置添加 Toast,但应用程序只会将内容添加到数据库中。

如果我省略名称,应用程序将触发定义的IllegalArgumentException,然后使应用程序崩溃。

这是content providerinsert 方法的sn-p

@Override
public Uri insert(Uri uri, ContentValues contentValues) {
    final int match = sUriMatcher.match(uri);
    switch (match) {
        case PATIENT:
            return insertPatient(uri, contentValues);
        default:
            throw new IllegalArgumentException("Insertion is not supported for " + uri);
    }
}

/**
 * Insert a patient into the database with the given content values.
 */
private Uri insertPatient(Uri uri, ContentValues values) {
    String name = values.getAsString(PatientEntry.COLUMN_PATIENT_NAME);
    if (name == null || name.length()==0) {
        //Toast.makeText(getContext(), "Patient requires a name", Toast.LENGTH_SHORT).show();
        throw new IllegalArgumentException("Patient requires a name");
    }

    Integer weight = values.getAsInteger(PatientEntry.COLUMN_PATIENT_WEIGHT);
    if (weight != null && weight < 0) {
        throw new IllegalArgumentException("Patient requires valid weight");
    }

    SQLiteDatabase database = mDbHelper.getWritableDatabase();

    long id = database.insert(PatientEntry.TABLE_NAME, null, values);
    if (id == -1) {
        Log.e(LOG_TAG, "Failed to insert row for " + uri);
        return null;
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return ContentUris.withAppendedId(uri, id);
}

这是来自活动文件的 sn-p

private void savePatient() {
    String nameString = mNameEditText.getText().toString().trim();
    String weightString = mWeightEditText.getText().toString().trim();

    if (mCurrentPatientUri == null &&
            TextUtils.isEmpty(nameString) && TextUtils.isEmpty(weightString) {
            Toast.makeText(this, "Data was not saved", Toast.LENGTH_SHORT).show();
        return;
    }

    ContentValues values = new ContentValues();
    values.put(PatientEntry.COLUMN_PATIENT_NAME, nameString);
    int weight = 0;
    if (!TextUtils.isEmpty(weightString)) {
        weight = Integer.parseInt(weightString);
    }
    values.put(PatientEntry.COLUMN_PATIENT_WEIGHT, weight);

    // Determine if this is a new or existing Patient by checking if mCurrentPatientUri is null or not
    if (mCurrentPatientUri == null) {
        // This is a NEW patient
        Uri newUri = getContentResolver().insert(PatientEntry.CONTENT_URI, values);

        if (newUri == null) {
            Toast.makeText(this, getString(R.string.editor_insert_patient_failed),
                    Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, getString(R.string.editor_insert_patient_successful),
                    Toast.LENGTH_SHORT).show();
        }
    } else {
        // Otherwise this is an EXISTING patient
        int rowsAffected = getContentResolver().update(mCurrentPatientUri, values, null, null);

        if (rowsAffected == 0) {
            Toast.makeText(this, getString(R.string.editor_update_patient_failed),
                    Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, getString(R.string.editor_update_patient_successful),
                    Toast.LENGTH_SHORT).show();
        }
    }
}

有人可以帮忙吗?

.................................................. .....

编辑 1:

这是activity中调用savePatient的菜单:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // User clicked on a menu option in the app bar overflow menu
    switch (item.getItemId()) {
        case R.id.action_save:
            savePatient();
            finish();
            return true;
        case R.id.action_delete:
            showDeleteConfirmationDialog();
            return true;
        case android.R.id.home:
            if (!mPatientHasChanged) {
                NavUtils.navigateUpFromSameTask(EditorActivity.this);
                return true;
            }

            // Otherwise if there are unsaved changes, setup a dialog to warn the user.
            DialogInterface.OnClickListener discardButtonClickListener =
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            NavUtils.navigateUpFromSameTask(EditorActivity.this);
                        }
                    };

            showUnsavedChangesDialog(discardButtonClickListener);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

【问题讨论】:

  • 无论哪个层发出请求,都需要捕获异常并显示合适的 UI。这层代码甚至不应该知道你的应用有一个 UI。

标签: android sqlite validation android-contentprovider


【解决方案1】:

对于视觉反馈验证,应尽早完成。 例如,在您对某些用户操作调用 save Patient 之前,只需调用 validatePatient() ,如果失败,则不会调用 save 。

对于视觉反馈,您可以在字段下方显示错误文本,仅当与该字段相关的验证失败时才会显示。

【讨论】:

  • 我已经编辑了我的问题以包含onOptionsItemSelected,所以我会在该开关块中的savePatient() 之前调用验证?
  • 是的,可以。像 validatePatient(){ if(newUri == null){ patientUriErrorTextView = (TextView)findViewById(R.id.patientUriErrorTextView); patientUriErrorTextView.setVisibility(View.VISIBLE);返回假; } 返回真; } 在你的 optionItemSelected 你可以做类似 if(validatePatient()){ savePatient();结束(); } 返回真;
  • 另外我建议不要膨胀你的活动责任,而是将这些任务委托给 ValidationHandler 之类的类,可以根据你的上下文将保存任务委托给 PatientRepositoryManager 或其他东西。 :)
猜你喜欢
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
  • 2012-07-17
  • 2021-12-09
  • 2021-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多