企业注册很多网站的好处,青岛简易付网络技术有限公司,wordpress 3.8,网站二级菜单是什么3 使用这个代码片段开始练习 也可以参考 Codepath 教程 高级内容补充: 你是否在思考ArrayAdapter’s 的 getView() 方法和CursorAdapter 的 newView() 和 bindView() 方法? 你可以查看 CursorAdapter 类的源码. getView() 方法依然存在, 但是它实际根据是否存在列表项能够被循…3 使用这个代码片段开始练习 也可以参考 Codepath 教程 高级内容补充: 你是否在思考ArrayAdapter’s 的 getView() 方法和CursorAdapter 的 newView() 和 bindView() 方法? 你可以查看 CursorAdapter 类的源码. getView() 方法依然存在, 但是它实际根据是否存在列表项能够被循环使用来决定调用 newView() 或 bindView()如果 convertView 为空那么我们需要创建新的列表项如果 convertView 不为空那么我们可以循环使用旧的列表项。 因此作为一个开发者我们不需要重载 CursorAdapter 的 getView() 方法. 我们可以仅仅重载 newView() 和 bindView() 方法, 剩下的工作交给适配器来完成 4 空视图是在 ListView 中无项目时展示的视图。在没有数据的情况下不是在应用中展示一个空白屏幕而是通过有吸引力的图像或描述性文字来提升用户体验。 文字甚至可以提示用户添加一些数据。 在我们的 Pets 应用中我们想要在 ListView 中没有要显示的宠物时设置以下空视图。 设置空视图非常简单。 第 1 步在 ListView 旁边创建空视图 首先在你的布局中创建空视图。在我们的案例中应该有两个 TextViews 和一个 ImageView像这样对齐。并给空视图一个 id“id/empty_view”以便我们之后在 Java 代码中引用。 red lines!-- Empty view for the list --RelativeLayout android:idid/empty_view android:layout_widthwrap_content android:layout_heightwrap_content android:layout_centerInParenttrue ImageView android:idid/empty_shelter_image android:layout_widthwrap_content android:layout_heightwrap_content android:layout_centerHorizontaltrue android:srcdrawable/ic_empty_shelter/ TextView android:idid/empty_title_text android:layout_widthwrap_content android:layout_heightwrap_content android:layout_belowid/empty_shelter_image android:layout_centerHorizontaltrue android:fontFamilysans-serif-medium android:paddingTop16dp android:textstring/empty_view_title_text android:textAppearance?android:textAppearanceMedium/ TextView android:idid/empty_subtitle_text android:layout_widthwrap_content android:layout_heightwrap_content android:layout_belowid/empty_title_text android:layout_centerHorizontaltrue android:fontFamilysans-serif android:paddingTop8dp android:textstring/empty_view_subtitle_text android:textAppearance?android:textAppearanceSmall android:textColor#A2AAB0/ /RelativeLayout 对于文本使用 strings.xml 资源文件。 !-- Title text for the empty view, which describes the empty dog house image [CHAR LIMIT50] --string nameempty_view_title_textIt\s a bit lonely here.../string !-- Subtitle text for the empty view that prompts the user to add a pet [CHAR LIMIT50] -- string nameempty_view_subtitle_textGet started by adding a pet/string 第 2 步添加空视图 在创建 ListView 时你可以使用 id 指定一个空视图。使用我们之前设置的 id用 findViewById() 方法获取视图然后使用 ListView 的 setEmptyView() 方法设置空视图。 // Find the ListView which will be populated with the pet dataListView petListView (ListView) findViewById(R.id.list);// Find and set empty view on the ListView, so that it only shows when the list has 0 items.View emptyView findViewById(R.id.empty_view);petListView.setEmptyView(emptyView);第 3 步测试 删除数据或卸载并重装应用使用一个空数据库启动。现在你应该会看到空视图出现在屏幕上 练习完成前后的差异。 6 参阅此教程 或此文档。 提示添加需要从接口实现的方法的键盘快捷键Ctrl I 提示将 CursorAdapter 作为全局变量 提示对于 onLoadFinished() 和 onLoaderReset() 方法你可以使用 CursorAdapter 的 swapCursor() 方法更改数据源 Cursor。 注插入新宠物从虚拟菜单项或编辑器不会自动更新宠物列表直到下一个编码任务前。你需要强制关闭应用并重新打开它才能看到宠物列表更新。 如果你在想为什么 projection 需要包含 _id请参见CursorAdapter 类的描述。CursorAdapter 假设 Cursor 包含一个名为 _id 的列。 7 目前我们的 CursorLoader 有一个小缺陷那就是它不会在底层 SQLite 数据库变化时进行自动更新。 为什么列表之前可以更新而现在不行我们返回去看看旧的代码。 在之前displayDatabaseInfo 在 onStart() 内及在菜单项被单击时调用。这可以完全确保数据始终为最新状态但它也会在主线程上多次进行不必要的数据加载。 在主线程上进行加载会降低应用的速度如我们之前所讲而且进行无用的加载更是浪费资源。 那么它什么时候的数据加载是无用的呢是这样每次当应用被旋转或你导航到别处一会儿并返回后 onStart 就会被触发。 如果你旋转应用或导航到别处并返回后你真的需要再次从数据库获取数据吗数据库中有任何东西发生变化了吗答案是没有数据库未发生任何变化所以你并不需要重新加载数据。 这实际上就是 CursorLoader 主要用于解决的问题之一我们想追踪数据是否已加载且如果已加载则避免重新加载除非有必要。 很显然我们不需要在每次调用 onStart 时重新加载方法。那么我们何时需要重新加载数据呢 查看答案提交答案解答 我们仅需要在 SQLite 数据库中的某些数据发生变化时更新Cursor。 用户关闭和重新打开应用、旋转应用和滚动 ListView 实际上不会更改数据库中的数据我们这时就不需要重新加载数据。 8 这个 教程 展示了何时调用notifyChange() Cursor setNotificationUri() 方法 9 注意在这里编辑器尚不会显示数据库中特定宠物的数据。这将在之后的步骤中实现。 提示 1通过 setOnItemClickListener() 方法将 OnItemClickListener 设置到 ListView。 提示 2创建特定宠物内容 URI使用 Uri.withAppendedId() 方法。 提示 3在 AndroidManifest.xml 中你可以删除 EditorActivity 活动元素中的 label 属性因为应用栏中新宠物和现有宠物情况的活动标题被在 Java 代码中通过编程方式覆写了。 10 好的现在我们的 Editor Activity 中有了宠物的 URI。在此情况下我们还应从内容提供程序 中加载宠物数据。我们可以使用 CursorLoader 进行加载。 这与我们上次使用 CursorLoader 的区别这次我们不是获取Cursor并将其放入 CursorAdapter而是获取Cursor中的所有项然后使用它们来填充 EditText 字段。 我们使用的步骤大体和之前一样只是当我们创建加载器时URI 将为单个宠物的而非全部宠物的。 然后我们从 onLoadFinished 中获得Cursor这时候我们不是使用 Cursor Adapter而是更新所有输入即包含宠物值的 editTexts 和性别 spinner。 最后在 onLoaderReset 方法中我们应清除输入字段。 现在花一些时间来实际操作吧。 你的步骤 实现加载器回调接口。初始化加载器。编写加载器回调方法 onCreateLoader 的代码确保它使用的是单个宠物的 URI。编写加载器回调方法 onLoadFinished 的代码并使用宠物数据更新输入。编写加载器回调方法 onLoaderReset 的代码然后清除输入字段。提示 1当你从加载器收到Cursor结果记得在开始从中提取列值前将Cursor移到位置 0。 提示 2你可以使用 Spinner 的 setSelection() 方法来设置下拉菜单 Spinner。 查看答案提交答案解答 首先实现加载器回调然后使用 Ctrl I 热键来获取所有加载器回调方法 public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacksCursor { 接下来使用此代码初始化加载器 getLoaderManager().initLoader(EXISTING_PET_LOADER, null, this);在 onCreateLoader() 中我将创建一个新的 CursorLoader传入 uri 和 projection。我需要从 onCreate() 获取 uri所以我需要将它放在一个名为 mCurrentPetUri 的实例变量 /** Content URI for the existing pet (null if its a new pet) */
private Uri mCurrentPetUri;...Override
public LoaderCursor onCreateLoader(int i, Bundle bundle) { // Since the editor shows all pet attributes, define a projection that contains // all columns from the pet table String[] projection { PetEntry._ID, PetEntry.COLUMN_PET_NAME, PetEntry.COLUMN_PET_BREED, PetEntry.COLUMN_PET_GENDER, PetEntry.COLUMN_PET_WEIGHT }; // This loader will execute the ContentProviders query method on a background thread return new CursorLoader(this, // Parent activity context mCurrentPetUri, // Query the content URI for the current pet projection, // Columns to include in the resulting Cursor null, // No selection clause null, // No selection arguments null); // Default sort order } 当宠物的数据加载到游标后onLoadFinished() 将被调用。在这里我首先要将游标移到第一个项的位置。尽快它只有一个项并从位置 -1 开始。 // Proceed with moving to the first row of the cursor and reading data from it// (This should be the only row in the cursor)if (cursor.moveToFirst()) {然后我将获得每个数据项的索引然后使用所有和 get() 方法抓取实际整数和字符串以从游标中获得数据。 if (cursor.moveToFirst()) {// Find the columns of pet attributes that were interested inint nameColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME);int breedColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED);int genderColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_GENDER); int weightColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_WEIGHT); // Extract out the value from the Cursor for the given column index String name cursor.getString(nameColumnIndex); String breed cursor.getString(breedColumnIndex); int gender cursor.getInt(genderColumnIndex); int weight cursor.getInt(weightColumnIndex); 对于每一个 textView我将设置适当的文本。 // Update the views on the screen with the values from the database mNameEditText.setText(name); mBreedEditText.setText(breed); mWeightEditText.setText(Integer.toString(weight)); 对于 Spinner我将使用一个 switch 语句来使用 setSelection 方法设置它的状态。 // Gender is a dropdown spinner, so map the constant value from the database// into one of the dropdown options (0 is Unknown, 1 is Male, 2 is Female).// Then call setSelection() so that option is displayed on screen as the current selection.switch (gender) {case PetEntry.GENDER_MALE: mGenderSpinner.setSelection(1); break; case PetEntry.GENDER_FEMALE: mGenderSpinner.setSelection(2); break; default: mGenderSpinner.setSelection(0); break; } 练习完成前后的差异 11 我们的“编辑宠物”(Edit Pet) 版本页面缺失一项重大功能那就是实际编辑宠物。 目前当你更改现有宠物的任何值时并不会更新宠物而是会保存宠物的一个副本这并非我们想要的。 解决方法就是使“编辑宠物”模式更新当前宠物使“添加宠物”模式插入新宠物。 这次我们不使用“insertPet”方法我们将它改名或“重构”为“savePet”。在这里就像我们之前一样你可以判断 EditorActivity 是“插入”模式还是“编辑”模式。如果为编辑模式你需要使用内容提供程序 执行一个“更新”操作。 好的现在来试一试吧更新 savePet 方法。完成后EditActivity 应该不会创建宠物的副本而是更新现有宠物。在你按下 FAB 按钮来插入新宠物时它也应正确执行。在这两种情况下你的应用都应显示 toast 消息。 提示如何判断我们是在“插入新宠物”还是“编辑现有宠物”你可以在设置 EditorActivity 标题时执行此检查。 注意确保在 strings.xml 文件中声明 toast 消息的字符串。 ContentResolver update() 示例。 查看答案提交答案练习完成前后的差异. 无论你是第一次更新宠物还是创建宠物你都需要使用 content values 对象。创建它的方式还是跟之前一样。创建好后你需要根据是要编辑现有宠物还是插入新宠物来进行不同操作。 你可以使用设置标题时所用的方法通过检查 mCurrentPetUri 是否为空值来区分编辑模式和插入模式。如果为空值那么就是新宠物你可以运行此方法中原有的代码。 if (mCurrentPetUri null) {如果 uri 不为空值这意味着你在更新现有宠物。你可以使用 ContentResolver 的 update 方法来更新宠物。你更新的内容的 URI 为 mCurrentPetUri这会简化代码编写。 } else {// Otherwise this is an EXISTING pet, so update the pet with content URI: mCurrentPetUri// and pass in the new ContentValues. Pass in null for the selection and selection args// because mCurrentPetUri will already identify the correct row in the database that// we want to modify. int rowsAffected getContentResolver().update(mCurrentPetUri, values, null, null); 现在它会返回已更新的列数。要显示更新是否成功我们可以检查已更新的列数。若为 0那么更新不成功则我们可以显示一条错误 toast 消息。若为相反情况则显示成功 toast 消息。 // Show a toast message depending on whether or not the update was successful.if (rowsAffected 0) {// If no rows were affected, then there was an error with the update.Toast.makeText(this, getString(R.string.editor_update_pet_failed), Toast.LENGTH_SHORT).show(); } else { // Otherwise, the update was successful and we can display a toast. Toast.makeText(this, getString(R.string.editor_update_pet_successful), Toast.LENGTH_SHORT).show(); } 12 干得不错 EditorActivity 在编辑模式下的主要功能已完成。 后续操作 我们依然需要实现 delete 和解决几个 bug。例如当你为插入新宠物而打开 EditorActivity 时你在没有输入任何东西时不小心点了保存按钮……这时候就会发生崩溃。 阅读错误消息我们得知这是因为你没有为体重输入数字基本上是因为它无法将空白值转换为数字。 通常情况下我们应在 UI 中要求用户在尝试将宠物信息存入数据库之前先输入一些宠物信息。而所有空白值应视为用户不小心按下保存键而非作为新宠物进行保存。 你的任务 你的任务就是解决这个 bug。为此首先你得检查输入是否为空字符串。你可以使用 TextUtils.isEmpty()) 方法来检查一个字符串是否全由空格或空字符串构成。如果所有的输入都为空字符串且根据 GENDER UNKNOWN 消息性别未更新则 savePet 方法会直接返回但不包含任何内容。 此外当你在保存新宠物时没有提供体重则宠物的给定体重将为 0而不会导致应用崩溃。 提示 1调用 finish() 方法来终止 activity。 提示 2如果输入字符串为空值或空字符串TextUtils.isEmpty(String s) 返回 true。 查看答案提交答案解答 我们要做的所有更改都在 EditorActivity.java 文件中进行特别是在 savePet() 方法中。 要解决第一个问题在我们获得所有值后但在创建 ContentValues 对象之前我将添加一个 if 语句来检查它们是否为空字符串及性别是否为未知。如果是我将不再执行剩余的方法或插入宠物而是直接返回。 if (mCurrentPetUri null TextUtils.isEmpty(nameString) TextUtils.isEmpty(breedString) TextUtils.isEmpty(weightString) mGender PetEntry.GENDER_UNKNOWN) {return;}在将体重放入 content value 对象之前我要解决的下一个问题是如果用户未指定宠物体重应将其设为 0而不是导致崩溃。所以在代码中我们将体重的默认值设为 0然后在用户输入体重后我会将其更改为输入的整数值。 // If the weight is not provided by the user, dont try to parse the string into an// integer value. Use 0 by default.int weight 0;if (!TextUtils.isEmpty(weightString)) { weight Integer.parseInt(weightString); } values.put(PetEntry.COLUMN_PET_WEIGHT, weight); 做了这些更改后应用便不会崩溃也不会保存完全空白的宠物信息。非常棒 练习完成前后的差异 13 警告用户 你可能注意到了按下 EditorActivity 的“上一个”(UP) 或“返回”(back) 按钮会使你离开 EditorActivity但不会保存你的更改。你想要明确保存数据库更改的方法那么我们只在用户点击“保存”(Save) 按钮的时候保存更改。 那么当用户在添加一些编辑时不小心按下“上一个”(UP) 或“返回”(back) 按钮时会怎样呢为避免用户丢失工作我们可以跳出一个对话框警告用户其在离开编辑器时有未保存的更改。 下面是联系人应用中的警告演示。当你输入新的联系人信息然后在未保存的情况下点击了“上一个”(UP) 按钮时你会看到此行为 期望的行为 在我们的应用中我们所期望的行为是跳出一个对话框用消息“是否放弃更改并退出编辑”(Discard your changes and quit editing?) 来警告用户。用户可以选择“继续编辑”(Keep Editing)即留在此活动或“放弃”(Discard)即结束活动。 步骤 第 1 步监听是否进行了更改 第一步是决定什么时候显示“放弃更改”对话框。这应仅在用户更改了表格的某一个部分时发生。你可以做的是创建一个名为 mPetHasChanged 的 boolean如果用户更新了 pet 表的任何部分则为 true。 private boolean mPetHasChanged false;你可以添加 OnTouchListener 来检查是否发生了更改 private View.OnTouchListener mTouchListener new View.OnTouchListener() {Overridepublic boolean onTouch(View view, MotionEvent motionEvent) { mPetHasChanged true; return false; } }; 在 onCreate 中 mNameEditText.setOnTouchListener(mTouchListener);mBreedEditText.setOnTouchListener(mTouchListener); mWeightEditText.setOnTouchListener(mTouchListener); mGenderSpinner.setOnTouchListener(mTouchListener); 第 2 步编写创建“放弃更改”对话框的方法 我们在下面编写一个创建此对话框的方法 private void showUnsavedChangesDialog(DialogInterface.OnClickListener discardButtonClickListener) {// Create an AlertDialog.Builder and set the message, and click listeners// for the positive and negative buttons on the dialog.AlertDialog.Builder builder new AlertDialog.Builder(this);builder.setMessage(R.string.unsaved_changes_dialog_msg);builder.setPositiveButton(R.string.discard, discardButtonClickListener);builder.setNegativeButton(R.string.keep_editing, new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {// User clicked the Keep editing button, so dismiss the dialog// and continue editing the pet.if (dialog ! null) {dialog.dismiss();}}});// Create and show the AlertDialogAlertDialog alertDialog builder.create();alertDialog.show();
}此代码使用 AlertDialogBuilder 创建了一个 AlertDialog。此方法接受放弃按钮的 OnClickListener。我们这样做是因为点击“返回”(back) 或“上一个”(up) 的行为略有不同。 并且注意我们还使用了很多 R.string你可以添加这些 Discard your changes and quit editing?DiscardKeep Editing第 3 步连接“返回”Back按钮 这是“返回”按钮的代码。你需要覆盖此活动的正常返回按钮。如果宠物发生了变化你建立会关闭当前活动的放弃点击侦听器。然后将此侦听器传入刚创建的 showUnsavedChangesDialog 方法。 Override
public void onBackPressed() {// If the pet hasnt changed, continue with handling back button pressif (!mPetHasChanged) {super.onBackPressed();return;}// Otherwise if there are unsaved changes, setup a dialog to warn the user.// Create a click listener to handle the user confirming that changes should be discarded.DialogInterface.OnClickListener discardButtonClickListener new DialogInterface.OnClickListener() {Overridepublic void onClick(DialogInterface dialogInterface, int i) {// User clicked Discard button, close the current activity.finish();}};// Show dialog that there are unsaved changesshowUnsavedChangesDialog(discardButtonClickListener);
}第 4 步连接“上一个”Up按钮 这里是“上一个”按钮的代码。它在 onOptionsItemSelected 方法中。如果宠物发生变化你建立一个会导航至“上一个”的放弃点击侦听器。然后将此侦听器传入刚创建的 showUnsavedChangesDialog 方法。 case android.R.id.home:// If the pet hasnt changed, continue with navigating up to parent activity// which is the {link CatalogActivity}.if (!mPetHasChanged) {NavUtils.navigateUpFromSameTask(EditorActivity.this);return true;}// Otherwise if there are unsaved changes, setup a dialog to warn the user.// Create a click listener to handle the user confirming that// changes should be discarded.DialogInterface.OnClickListener discardButtonClickListener new DialogInterface.OnClickListener() {Overridepublic void onClick(DialogInterface dialogInterface, int i) {// User clicked Discard button, navigate to parent activity.NavUtils.navigateUpFromSameTask(EditorActivity.this);}};// Show a dialog that notifies the user they have unsaved changesshowUnsavedChangesDialog(discardButtonClickListener);return true;练习完成前后的差异 有用链接 要向“返回”back按钮被点击的情况添加行为参阅此 StackOverflow 帖子。 要向“上一个”Up按钮被点击的情况添加行为参阅此文章。你还需要向 android.R.id.home 按钮被点击的情况添加代码。 如何创建 AlertDialog。 14 如果宠物还不存在则无法删除它 我们当前的代码还有一个“问题”那就是当你处于 EditorActivity 的插入模式时会在菜单中看到一个“删除”(Delete) 选项。由于你当前在插入宠物因此没有宠物可供删除那么这个选项是多余的。 我们来解决这个问题。我们要删除“插入模式”中的删除选项。 如何选择运行应用时的菜单 当你第一次打开活动时会调用 onCreateOptionsMenu 方法。它会用所有可见的菜单项填充菜单。要更改它你需要做的是在确定它是一个新宠物后mPetContentUri 为空值你要使选项菜单无效。 所以在 onCreate 中…… if (mCurrentPetUri null) {// This is a new pet, so change the app bar to say Add a PetsetTitle(getString(R.string.editor_activity_title_new_pet));// Invalidate the options menu, so the Delete menu option can be hidden.// (It doesnt make sense to delete a pet that hasnt been created yet.) invalidateOptionsMenu(); } else { //other stuff } 然后onPrepareOptionsMenu 会被调用你可以在它是新宠物时隐藏删除菜单选项来修改菜单对象。 此操作的代码如下 Overridepublic boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); // If this is a new pet, hide the Delete menu item. if (mCurrentPetUri null) { MenuItem menuItem menu.findItem(R.id.action_delete); menuItem.setVisible(false); } return true; } 练习完成前后的差异 有用链接 Android开发文档菜单选项 Stack Overflow 提问如何改变菜单项 15 我们的最后一项重大任务是实现删除宠物的能力。此功能在应用的两个地方第一个是在 EditorActivity 页面的菜单中当你更新宠物时会用到。 第二个是在 CatalogActivity 的菜单中在此处删除 (delete) 选项可用于删除所有宠物你在测试数据库时可以使用。 首先我们来看 EditorActivity 中的 delete 方法。我们已添加了使它仅在“编辑宠物”模式出现的代码。现在我想要实现的功能是当我们选择删除宠物时出现一个对话框 即按下删除按钮应出现一条 toast 消息“已删除宠物”(Pet deleted) 并从数据库中删除宠物。 我们复制此代码片段。它包含 tring.xml 的一些新字符串也包含生成对话框的代码位于一个名为“showDeleteConfirmationDialog”的方法和一个空的“deletePet”方法中。 此对话框有两个 onClick 侦听器一个用于这里显示的“删除”(delete) 按钮另一个用于这里显示的“取消”(cancel) 按钮。Delete 对话框调用空的“deletePet”方法你需要在这个方法中添加代码来实际删除当前宠物。 你的任务 首先找到代码中正确的位置以当你从下拉菜单中选择“删除宠物”(Delete Pet) 时它会打开 DeleteConfirmationDialog。 接下来填上deletePet 方法以删除当前宠物。你应仅在“编辑模式”中删除宠物。你还应显示一条 toast 消息说明是否删除了宠物方法和我们之前用 toast 消息表明是否成功更新了宠物一样。 ContentResolver delete() 示例 查看答案提交答案解答 在复制代码片段后首先我们要通过在按下删除按钮时调用 showDeleteConfirmationDialog 方法来确保触发它。方法是前往 onOptionsItemSelected 并在 action.delete 下添加对 showDeleteConfirmationDialog 的调用。 // Respond to a click on the Delete menu optioncase R.id.action_delete:// Pop up confirmation dialog for deletionshowDeleteConfirmationDialog();showDeleteConfirmationDialog 会创建一个对话框在删除按钮被按下时调用 deletePet。首先我确保我们是对现有宠物执行删除。因为对数据库中尚不存在的新宠物执行删除是没有意义的。所以我检查是否存在现有宠物mCurrentPetUri 是否等于 null。然后使用 content resolver 和当前的宠物 uri 删除宠物。 /*** Perform the deletion of the pet in the database.*/
private void deletePet() {// Only perform the delete if this is an existing pet.if (mCurrentPetUri ! null) { // Call the ContentResolver to delete the pet at the given content URI. // Pass in null for the selection and selection args because the mCurrentPetUri // content URI already identifies the pet that we want. int rowsDeleted getContentResolver().delete(mCurrentPetUri, null, null); delete 方法和 update 方法一样会返回被删除的行数。我可以通过检查被删除的行数是否为 0 来确定删除成功与否。若为 0则删除失败我会显示一条 toast 消息说明“删除宠物时出错”(Error with deleting pet)。 否则操作将是成功的且我跳出一条 toast 消息说“宠物已删除”(Pet deleted)。 // Show a toast message depending on whether or not the delete was successful.if (rowsDeleted 0) {// If no rows were deleted, then there was an error with the delete.Toast.makeText(this, getString(R.string.editor_delete_pet_failed), Toast.LENGTH_SHORT).show(); } else { // Otherwise, the delete was successful and we can display a toast. Toast.makeText(this, getString(R.string.editor_delete_pet_successful), Toast.LENGTH_SHORT).show(); } 完成操作后调用 finish() 方法关闭此 activity。 // Close the activityfinish();到此我们就能成功从 EditorActivity 中删除宠物了 练习完成前后的差异. 16 现在我要你添加当用户从 CatalogActivity 上的溢出菜单点击“删除所有宠物”(Delete All Pets) 选项时用于删除所有宠物的代码。无需添加确认消息但是如果你想也可以自行实现。 完成后菜单看起来应该是这样的 这里的变更较小所以我就不多做讲解由你自己来完成。 Android 中的 菜单选项。 查看答案提交答案解答 对于此练习我们在 CatalogActivity.java 文件中进行。 此菜单按钮与 R.id.action_delete_all_entries 关联所以在 onOptionsMenuSelected 方法的该 case 下我将添加对名为“deleteAllPets()”方法的调用。 case R.id.action_delete_all_entries:deleteAllPets();return true;然后在该方法中我将使用 ContentResolver 的 delete 方法并传入PetEntry.CONTENT_URI。为什么要用内容 URI因为这是一个一般 __/pets uri在我们的 内容提供程序中将删除所有宠物。 /*** Helper method to delete all pets in the database.*/
private void deleteAllPets() {int rowsDeleted getContentResolver().delete(PetEntry.CONTENT_URI, null, null); Log.v(CatalogActivity, rowsDeleted rows deleted from pet database); } 此菜单按钮与R.id.action_delete_all_entries 关联所以在 onOptionsMenuSelected 方法的该 case 下我将添加对名为“deleteAllPets()”方法的调用。 练习完成前后的差异. 17 对于我们的最后一项更新你需要解决 UI 中的另一个奇怪的行为。当品种未知时宠物列表看起来总觉得缺点什么。因为宠物名下就是一片空白。 在未提供品种信息的情况下比起留白显示一个语句“品种未知”(Unknown breed) 会提供更好的用户体验。 完成此步后应用看起来应该是这个样子的 注意这只是 CatalogActivity 中的一个 UI 变化文本“Unknown breed”不应保存在数据库中。如果你在编辑器中打开此宠物“品种”(breed) 字段应该是空白的 提示如果输入字符串为空值或空字符串TextUtils.isEmpty(String s) 将返回 true。 查看答案提交答案解答 首先由于我们要添加字符串“Unknown breed”我们在 strings.xml 文件中保存它。 !-- Label for the pets breed if the breed is unknown [CHAR LIMIT20] --
string nameunknown_breedUnknown breed/string 接下来我们移至 PetCursorAdapter.java 文件。当我们在 CatalogActivity 中显示宠物时我们要检查是否有使用 TextUtils.isEmpty 方法的品种。如果没有我们将列表项的 TextView 设为显示“Unknown breed”。 In PetCursorAdapter.java: /*** This method binds the pet data (in the current row pointed to by cursor) to the given* list item layout. For example, the name for the current pet can be set on the name TextView* in the list item layout.** param view Existing view, returned earlier by newView() method* param context app context* param cursor The cursor from which to get the data. The cursor is already moved to the* correct row.*/
Override public void bindView(View view, Context context, Cursor cursor) { // Find individual views that we want to modify in the list item layout TextView nameTextView (TextView) view.findViewById(R.id.name); TextView summaryTextView (TextView) view.findViewById(R.id.summary); // Find the columns of pet attributes that were interested in int nameColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME); int breedColumnIndex cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED); // Read the pet attributes from the Cursor for the current pet String petName cursor.getString(nameColumnIndex); String petBreed cursor.getString(breedColumnIndex); // If the pet breed is empty string or null, then use some default text // that says Unknown breed, so the TextView isnt blank. if (TextUtils.isEmpty(petBreed)) { petBreed context.getString(R.string.unknown_breed); } // Update the TextViews with the attributes for the current pet nameTextView.setText(petName); summaryTextView.setText(petBreed); } 练习完成前后的差异. 转载于:https://www.cnblogs.com/infocodez/p/8449730.html