第五章:Reminders實驗:第一部分[Learn Android Studio 漢化教程]

By now you are familiar with the basics of creating a new project, programming, and refactoring.It is time to create an Android application, otherwise known as an app. This chapter introduces the first of four lab projects. These labs are intended to familiarize you with using Android Studio in the context of developing an app. In this project, you will develop an app to manage a list of items you want to remember. The core functionality will allow you to create and delete
reminders and flag certain reminders as important. An important item will be emphasized by an orange tab to the left of the reminder’s text. The app will incorporate an action bar menu, context menus, a local database for persistence, and multiple selection on devices that support multiple selection.
<翻譯>
到如今爲止你已經熟悉了建立一個新項目,編程,和重構的基本操做了。是時候建立一個Android 應用了,或者說成咱們所謂的APP。這章將介紹四個實例項目的第一個。這些實例目的是讓你熟悉使用Android Studio開發APP的上下文方面。核心功能是容許你建立和刪除一個提醒以及標誌那些重要的提醒。重要的條目文體左邊將被強調黃色標籤。這個APP將合同一個動做條菜單,上下文菜單,一個本地的數據庫做存儲,若是設備支持的話還有多重選擇。

Figure 5-1 illustrates the completed app running on the emulator. This example introduces you to Android fundamentals and you will also learn how to persist data by using the built-in SQLite database. Don’t worry if some of the topics are unfamiliar; later chapters cover those topics in greater detail.
<翻譯>
圖5-1圖示了仿真器上完成的app。這個例子介紹了Android基礎而且你也會學到如何用內建的SQLite數據庫來保存數據。別擔憂那些你不熟悉的話題,後續的章節將涵括這些話題大量的細節。

Note We invite you to clone this project using Git in order to follow along, though you will be recreating this project with its own Git repository from scratch. If you do not have Git installed on your computer, see Chapter 7. Open a Git-bash session in Windows (or a terminal in Mac or Linux) and navigate to C:\androidBook\reference\ (If you do not have a reference directory, create one. On Mac navigate to /your-labs-parent-dir/reference/) and issue the following git command: git clone  https://bitbucket.org/csgerber/reminders.git Reminders.
<翻譯>
注意:爲了一致性,咱們建議你用Git克隆這個項目,雖然你將從草稿裏用它自身的Git存儲庫重建這個項目。若是你尚未安裝Git,請看第7章。在窗口裏打開一個Git-bash會話(在Mac或Linux裏的終端)並導航到C:\androidBook\reference\<譯者注:在Git-bash控制檯裏可使用Dos命令cd c:改當前盤爲C;dir查看當前目錄文件;cd androidBook進入androidBook子目錄;cd reference進入reference子目錄>(若是沒有這個目錄建立它)並提交下面的Git命令:git clone  https://bitbucket.org/csgerber/reminders.git Reminders。


圖5-1 完成的app界面

To operate the Reminders app, you can use the overflow menu of the Action Bar. Tapping the overflow button, which looks like three vertical dots on the right side of the menu bar, opens a menu with two options as shown in Figure 5-2: New Reminder, and Exit. Tapping New Reminder opens a dialog box as shown in Figure 5-3. In the dialog box, you can add text for your new reminder and then tap Commit to add it to the list. Tapping Exit simply
quits the app.
<翻譯>
操做Reminders這個app,你能夠用動做條的溢出菜單。點擊溢出按鈕,在菜單欄右側,看起來象垂直點,打開一個菜單如圖5-2有兩個選項:新提醒,和退出。點擊新提醒打開一個對話框如圖5-3。在這個對話框裏,你能夠爲新提醒加入文本而且點提交加到清單裏。點擊退出。


圖5-2 激活溢出菜單的app界面


圖5-3 新提醒對話框

Tapping any reminder in the list opens a context menu with two options, shown in Figure 5-4:Edit Reminder and Delete Reminder. Tapping Edit Reminder from the context menu opens the Edit Reminder pop-up dialog box shown in Figure 5-5, where you can change the text of the reminder. Tapping Delete Reminder from the context menu deletes the reminder from the list.
<翻譯>
點擊清單中的隨意一個提醒有兩個可選方式,如圖5-4:編輯提醒和刪除提醒。從上下文菜單中點編輯提醒,彈出對話框如圖5-5所示,在那裏你能夠修改提醒裏的文本。點擊刪除提醒則會刪掉這個提醒。


圖5-4 上下文菜單


圖5-5 編輯提醒對話框

Starting a New Project

Start a new project in Android Studio by using the New Project Wizard as explained in Chapter 1. Enter Reminders as the application name, set the company domain to gerber.apress.com, and choose the Blank Activity template. Save this project under the path C:\androidBook\Reminders. It’s a good idea to keep all of your lab projects in a common folder such as C:\androidBook (or use ~/androidBook for Mac/Linux) for consistency with our examples. On the next page of the wizard, select Phone and Tablet and set the Minimum SDK to API 8: Android 2.2 (Froyo). By setting your min API level to 8, you are making your app available to more than 99% of the Android market. Click the Next button, choose the Blank Activity from the available templates, and click Next again. Set the activity name to RemindersActivity and then click Finish, as shown in Figure 5-6.
<翻譯>
開始一個新項目
在Android Studio開始一個新的項目,用新項目嚮導如同在第1章裏所介紹的。輸入Reminders做爲項目名,設置公司域名爲gerber.apress.com,並選Blank Activity模板。保存到C:\androidBook\Reminders。爲了咱們例子的一致性,這是一個好主意保存你全部的實驗項目到同一個目錄,好比C:\androidBook (or use ~/androidBook 對於 Mac/Linux來講)。在嚮導的下一頁,選擇電話和掌上設備並設置最低支持SDK到API 8:Android 2.2(凍酸奶)。經過設定最低支持SDK到API 8,你讓這個app支持目前市場上99%的設備。點擊下一步按鈕,選擇Blank Activity,再點下一步。設置activity名稱爲RemindersActivity並點完成,如圖5-6所示。


圖5-6 輸入activity名稱

Android Studio displays activity_reminders.xml in Design mode. The activity_reminders.xml file is the layout for your main activity, as shown in Figure 5-7. As discussed in Chapter 1, the project should run on either an emulator or a device at this point. Feel free to connect your device or launch your emulator and the run the project to try it out.
<翻譯>
Android Studio在設計模式下顯示activity_reminder.xml。這是你的主activity的佈局,如圖5-7示。如同第1章所討論的,在這刻項目能夠運行在仿真器上或設備上。只要你樂意隨便用哪一個。


圖5-7 activity_reminders的設計模式

Initializing the Git Repository

Your first step after creating a new project should be to manage the source code with version control. All the labs is this book use Git, a popular version-control system that works seamlessly with Android Studio and is available online for free. Chapter 7 explores Git and version control more thoroughly.
<翻譯>
初始化Git存儲庫
創建新項目後的第一步必須是用版本控制來管理源代碼。全部這本書的例子都用Git,一個流行的版本控制系統,無縫地協同Android Studio工做而且一直是在線免費的。第7章更完全地探索了Git和版本控制。

If you do not already have Git installed on your computer, please refer to the section entitled Installing Git in Chapter 7. Choose VCS ➤ Import into Version Control ➤ Create Git Repository from the main menu. (In the Apple OS, choose VCS ➤ VCS Operations ➤ Create Git Repository.) Figures 5-8 and 5-9 demonstrate this flow.
<翻譯>
若是你還沒安裝Git,請參考第7章。從主菜單選擇VCS>Import into Version Control>Create Git
Repository。(在IOS上,選擇VCS >VCS Operations>Create
Git Repository)圖5-8和5-9展現了這個流程。


圖5-8 建立一個Git存儲庫


圖5-9 爲Git存儲庫選擇根目錄

When prompted to select the directory for Git init, make sure that the Git project will be initialized in the root project directory (again, called Reminders in this example). Click OK.
<翻譯>
當提示選擇Git的初始目錄,確認初始化爲項目的根目錄(再次,在這個例子裏是Reminders)。點擊OK。

You will notice that most of the files located in the Project tool window have turned brown, which means that they are being tracked by Git but have not yet been added to the Git repository nor are they scheduled to be added. Once your project is under Git’s control, Android Studio uses a coloring scheme to indicate the status of files as they are created, modified, or deleted. This coloring scheme will be explained in more detail as we progress though you can research this topic in more detail here: jetbrains.com/idea/help/file-status-highlights.html.
<翻譯>
你將注意到項目工具窗裏大部分文件變成棕色的,意味着它們被Git跟蹤但還沒加入到Git的存儲庫並且時刻表也沒加載。一但你的項目被Gitr控制,Android Studio使用一個色彩策略,隨着咱們項目的進行將會解釋更多的細節。固然你也可能在這:jetbrains.com/idea/help/file-status-highlights.html得更多的細節,若是你想研究的話。

Click the Changes tool button located along the bottom margin to toggle open the Changes tool window and expand the leaf labeled Unversioned Files. This will show all files that are being tracked. To add them, select the Unversioned Files leaf and press Ctrl+Alt+A | Cmd+Alt+A or right-click the Unversioned Files leaf and choose Git ➤ Add. The brown files should have turned green, which means that they have been staged in Git and are now ready to be committed.
<翻譯>
點擊位於窗口底部邊緣的Changes工具按鈕切換打開Changes工具窗口並展開葉子標籤的未受版本控制文件。這將顯示全部被跟蹤的文件。爲加載它們,選擇未受版本控制文件葉子並按Ctrl+Alt+A | Cmd+Alt+A或右擊未受版本控制文件葉子並選擇Git>Add。棕色文件將會變成綠色,意味着它們在Git中已階段化並且如今準備被提交了。

Press Ctrl+K | Cmd+K to invoke the Commit Changes dialog box. Committing files is the process of recording project changes to the Git version control system. As shown in Figure 5-10, the Author drop-down menu is used to override the current default committer. You should leave the Author field blank, and Android Studio will simply use the defaults you initially set during your Git installation. Deselect all check-box options in the Before Commit section. Put the following message in the Commit Message field: Initial commit using new project wizard. Click the Commit button and select Commit again from the drop-down items.
<翻譯>
按Ctrl+K | Cmd+K來調用提交更改對話框。提交文件是Git版本控制系統記錄項目更改的一個過程。如圖5-10所示,受權者下拉菜單用於重寫當前缺省提交者。讓這欄空着吧,這樣Android Studio將簡單地用你安裝Git時設的缺省值。去選Before Commit多選框裏全部的選項。把下面的信息放入到Commit Message區裏:Initial commit using new project wizard。點擊提交按鈕並在下拉條目裏再次選擇提交。


圖5-10 提交更改到Git

By default, the Project tool window should be open. The Project tool window organizes your project in different ways, depending on which view is selected in the mode drop-down menu at the top of the window. By default, the drop-down menu is set to Android view, which organizes the files according to their purpose and has nothing to do with the way the files are organized on your computer’s operating system. As you explore the Projects tool window, you will notice three folders under the app folder: manifests, java, and res. The manifests folder is where your Android manifest files can be found. The java folder is where your Java source files may be found. The res folder holds all of your Android resource files. The resources located under the res directory may be XML files, images, sounds, and other assets that help define the appearance and UI experience of your app. Once you’ve had the opportunity to explore Android view, we recommend switching to Project view which is more intuitive because it maps directly to the file structure on your computer.
<翻譯>
默認狀況下,項目工具窗將會打開。項目工具窗以不一樣的方式組織你的項目,取決於頂部窗口的下拉菜單所選擇的示圖。缺省地,下拉菜單是Android示圖,它按文件目的組織文件而不是按你電腦操做系統組織文件的方式。當你展開項目工具窗,將注意到三個文件夾在app文件夾下:manifests, java, 和 res。Manifests文件夾裏有你的Android manifest文件。Java文件夾是存放java 源文件的地方。Res文件夾保存全部你的Android資源文件。在res目錄下的資源多是XML文件,圖象,聲音,和其餘資源用於幫助定義你的app外觀和用戶體驗。一但你有機會展開Android示圖,咱們推薦切換到Project示圖,它更直觀由於它直接反映了你電腦上的目錄結構。

Building the User Interface

By default, Android Studio opens the XML layout file associated with the main activity in a new tab of the Editor and sets its mode to Design, so the Visual Designer is typically the first thing you see in your new project. The Visual Designer lets you edit the visual layout of your app. In the middle of the screen is the Preview Pane. The Preview Pane displays a visual representation of an Android device while rendering the results of the layout you are currently editing. This representation can be controlled by using the preview layout controls across the top of the screen. These controls adjust the preview and can be used to select different (or multiple) flavors of Android devices, from smartphones to tablets or wearables. You can also change the theme associated with your layout description. On the left side of the screen, you’ll find the Control palette. It contains various controls and widgets that can be dragged and placed onto the stage, which is a visual representation of the device. The right side of the IDE contains a component tree that shows the hierarchy of components described in your layout. The layout uses XML. As you make changes in the Visual Designer, these changes are updated in XML. You can click the Design and Text tabs to toggle between visual- and text-editing modes. Figure 5-11 identifies several key areas of the Visual Designer.
<翻譯>
構建用戶界面
默認狀況下,Android Studio打開與主activity相關聯的XML佈局文件在一個新的編輯選項卡里並設置爲設計模式,於是一般你在新項目裏先看到的是可視化開發器。可視化開發器讓你編輯app的可視化佈局。在屏幕的中央是預覽面板。預覽面板是Android設備渲染你當前編輯的佈局結果的虛擬展現。這個展現可控於屏幕上方橫跨的佈局預覽控制。這些控制可調整預覽並選擇不一樣風格的Android設備,從智能電話到穿戴設備。你也能夠改變佈局裏所描述的相關主題。屏幕的左邊,你會發現控件板。包含了衆多的控件和widget,它們可被拖放到正虛擬展現的設備平臺上。IDE的右側包含了一個組件樹展現了佈局裏組件的層次關係。佈局使用XML文件。當你在這個可視化開發器做出修改時,這些修改將更新於XML中。你可選擇Design或Text選項卡來切換可視化或是文本編輯模式。圖5-11標識幾個可視化開發器關鍵區域。


圖5-11 可視化開發器界面

Working with the Visual Designer

Let’s start by creating a list of reminders. Click the Hello World TextView control on the stage and then press Delete to remove it. Find the ListView control in the palette and drag it onto the stage. As you drag, the IDE will display various measurement and alignment guidelines to help you position the control which will tend to snap to the edges as you drag close to them. Drop the ListView so that it aligns with the top of the screen. You can position it either at the top-left or the top-center. After it is positioned, find the Properties view on the lower-right side of the Editor. Set the id property to reminders_list_view. The id property is a name you can give to controls that allows you to reference them programmatically in Java code; and this is how we will refer to the ListView later when we modify the Java source code. Change the layout:width property in the Properties window and set it to match_parent. This will expand the control so that it occupies as much space as the parent control it lives within. You will learn more about the details of designing layouts in Chapter 8. For now, your layout should resemble Figure 5-12.
<翻譯>
工做於圖形化編輯器
讓咱們開始建立reminders的列表項吧。在平臺上點擊Hello World文本框並刪除它。找到ListView控件並拖放到平臺裏。當你拖動時,IDE將顯示變化着的尺寸度量以及排列參考來幫助你定們控件,那些當你拖動靠近它們時會企圖抓住邊緣。拖放listView它會在屏幕頂部排列。你能夠定位在頂部的左邊或中間。在定位後,找到在編輯器右下側的屬性示圖。設置id屬性爲reminders_list_view。Id屬性是你能夠在JAVA代碼裏控件編程參考;且這個是咱們將如何參考的ListView在以後修改代碼時。修改layout:width屬性設置爲match_parent。這將擴展控件動態地佔有儘量多的父控件寬度。關於佈局在第8章裏你會學到更多細節。如今,你的佈局將裝配成圖5-12那樣。


圖5-12 有個ListView的activity_reminders的佈局

In Android, an activity defines the logic that controls user interaction with your app. When learning Android for the first time, it helps to think of an activity as a screen within your app, though activities can be more complicated than that. These activities typically inflate a layout which define where things appear on-screen. The layout files are defined as XML but can be edited visually using the Visual Designer as described earlier.
<翻譯>
在Android裏,一個activity定義了控制用戶和app交互的邏輯。當第一次學Android時,把activity想象成你的app的一個屏幕是對你有幫助的,雖然activity要比這個複雜得多。佈局文件定義爲一個XML,但用早先提到的圖形化編輯器能夠圖形化編輯。

Editing the Layout’s Raw XML

Click the Text tab along the bottom to switch from visual editing to text editing. This brings up a view of the raw XML for the layout, along with a live preview to the right. Changes you make to the XML are immediately reflected in the preview pane. Change the background color of the RelativeLayout to a dark grey by inserting android:background="#181818" underneath the line which reads android:layout_height="match_parent". Colors are expressed in hexadecimal values. See Chapter 9 for more information on hexadecimal color values. Notice that there is now a dark-grey swatch that appears in gutter next to the line you inserted which set the background color of the root ViewGroup.If you toggle back to Design mode, you will observe that the entire layout is now dark-grey.
<翻譯>
編輯佈局的原生XML
點擊編輯器左下方的文本選項卡,從圖形化編輯切換到文本編輯模式。這帶來了佈局的原生XML示圖,右邊伴隨着一個預覽面板。將RelativeLayout的背景色改成黑色,插入這行:android:background="#181818" 到android:layout_height="match_parent"下面。顏色用十六進制來表達。能夠看下第9章關於十六進制顏色的更多信息。注意到你插入那條設置根示圖背景色那行後夾縫裏的黑灰色的樣本。若是你回到設計模式,會觀察到整個佈局變成黑灰色了。

Hard-coding a color value directly in your XML layout file is not the best approach. A better option is to define a colors.xml file under the values resource folder and define your colors there. The reason we externalize values to XML files such as colors.xml is that these resources are kept and edited in one place and they can be referenced easily throughout your project.
<翻譯>
直接用硬編碼一個顏色值到你的XML文件裏不是最好的途徑。更好的選擇是定義一個colors.xml文件到資源文件夾裏,並在那定義你的顏色。在XML文件(如colors.xml)裏實現值的緣由是那些資源被保存和編輯在一個地方而且在在整個項目裏能夠輕鬆地參考。

Select the hex value #181818 and cut it to your clipboard by using Ctrl+X | Cmd+X or by choosing Edit ➤ Cut. Type @color/dark_grey in its place. This value uses special syntax to refer to an Android color value named dark_grey. This value should be defined in an Android resource file called colors.xml, but because this file does not yet exist in your project, Android Studio highlights this error in red. Press Alt+Enter and you will be prompted with options to correct the error. Select the second option, Create Color Value Resource dark_grey, and then paste the value in the Resource value: field of the next dialog box that appears and click Ok.
<翻譯>
用Ctrl+X | Cmd+X 或經過主菜單的 Edit ➤ Cut選擇十六進制的顏色值#181818並剪切它到粘貼板。輸入@color/dark_grey到這個位置。這是一個特殊的語法參考到Android資源文件colors.xml,但這個文件還不存在於你的項目裏,Android Studio會高亮紅色指出這個錯誤。按Alt+Enter會提示糾正這個錯誤的選項。選擇第二個選項,建立顏色資源dark_grey,接着把剛纔的顏色值粘貼到資源值裏:下個出現的對話框值域並點擊OK。

The New Color Value Resource dialog box will create the Android resource file colors.xml and fill it with the hexadecimal value. Click OK and then click OK in the Add Files to Git dialog box to have this new file added to version control and be sure to select the Remember, Don’t Ask Again checkbox so that you’re not bothered with this message again. Figure 5-13 demonstrates this flow.
<翻譯>
新顏色值資源對話框將建立Android資源文件colors.xml並填充十六進制的值。點擊OK接着在加入文件到Git對話框裏仍是點OK,這個新文件加入到版本控制,並確保選擇Remember,Don’t Ask Again這個複選框於是這個信息下次不會再打擾你了。圖5-13演示了這個流程。




圖5-13 析出硬代碼顏色值到一個資源文件
The ListView in preview mode contains row layouts that do not provide enough contrast with our chosen background color. To change the way these items appear, you will define a layout for the row in separate layout file. Right-click the layout folder under the res folder and choose New ➤ Layout Resource File. Enter reminders_row in the New Resource File dialog box. Use LinearLayout as the root ViewGroup and keep the rest of the defaults as seen in Figure 5-14.
<翻譯>
在預覽模式下這個ListView控件包含的行佈局在咱們所選的背景色時沒有足夠的對比度。要改變這項表象,你將在另一個佈局文件裏定義該佈局。右擊資源文件夾裏的佈局文件夾並選擇New ➤ Layout Resource File。在新資源文件對話框裏輸入reminders_row。在根示圖組裏用線性佈局並讓其餘的爲默認值,如圖5-14所示。


圖5-14 新資源文件對話框

You will now create the layout for an individual list item row. The LinearLayout root ViewGroup is the outermost element in the layout. Set its orientation to vertical by using the controls in the toolbar at the top of the preview pane. Be careful when you use this control because horizontal lines indicate a vertical orientation and vice versa. Figure 5-15 highlights the Change Orientation button.
<翻譯>
你如今將建立列表項獨立的佈局。線性佈局的根示圖組在佈局裏是最外層的元素。在預覽面板頂部的工具欄控制鈕設置其走向爲垂直方向。當你用這個控制鈕時當心點,由於水平線條表示的是垂直方向,反之亦然。圖5-15高亮了這個走向按鈕。


圖5-15 修改走向按鈕

Find the properties view along the bottom right of the preview pane. Find the layout:height property and set it to 50dp. This property controls the height of a control, and the dp suffix refers to the density-independent pixels measurement. This is a metric that Android uses to allow layouts to scale properly regardless of the screen density on which they are rendered. You can click any property in this view and start typing to incrementally search for properties, and then press the up- or down-arrows to continue searching.
<翻譯>
在預覽面板的右下方找到屬性示圖。找到layout:height屬性並設爲50dp。這個控制控件的高度,dp這個單位參照像素獨立密度度量系統。這是公開的,Android容許佈局參照屏幕重繪時的密度合適地縮放。你能夠點擊這個示圖裏的任意屬性並增量鍵入搜索屬性,並按上下鍵繼續搜索。

Drag and drop a horizontal LinearLayout inside the vertical LinearLayout. Drag and drop a CustomView control inside the horizontal LinearLayout and set its class property to android. view.View to create a generic empty view and give it an id property of row_tab. As of this writing, there is a limitation in Android Studio that does not allow you to drag a generic View from the palette. Once you click CustomView, you will get a dialog box with different choices, none of which include the generic View class. Select any class from the dialog and place it in
your layout. Find the class property of the view you just placed using the properties window in the properties pane to the right and change it to android.view.View to work around this limitation. Refer to Listing 5-1 to see how this is done.
<翻譯>
拖放一個水平線性佈局到垂直線性佈局裏。拖放一個自定義控件到水平線性控件裏並設置它的類屬性爲android.view.View,來建立一個通用的空示圖並付予id爲row_tab。在寫這篇文章時,Android Studio仍是有點侷限:它不容許你從控件板裏拖放通用示圖。當你點擊CustomView時,將獲得一個有不一樣選項的對話框,沒有一個包括了通用的View類。選擇任意一個類並放到你的佈局裏。爲這個限制的狀況找到類屬性並修改成android.view.View。對照清單5-1看看如何完成它

You will use this generic View tab to flag certain reminders as important. With the edit mode still set to Text, change your custom View’s layout:width property to 10dp and set its layout:height property to match_parent. Using the match_parent value here will make this View control as tall as its parent container. Switch to Design mode and drag and drop a Large Text control inside the horizontal LinearLayout of the Component Tree and set its width and height properties to match_parent. Verify that your Large Text component is positioned to the right of the custom view control. In the Component Tree, the component labelled textView should be nested inside the LinearLayout (horizontal) component and underneath the view component. If textView appears above view, drag it down with your mouse so that it snaps to the second (and last) position. Give your TextView control an id value of row_text and set its textSize property to 18sp. The sp suffix refers to the caleindependent
pixels measurement which performs like dp, but also respects the user’s text size settings so that, for example, if the user were hard of sight and wanted text on her phone to display large, sp would respect this setting, whereas dp would not. Therefore, it’s always a good idea to use sp for textSize. You will learn more about screen measurements in Chapter 8.
<翻譯>
你將會用到這個通用的View選項卡來標記那些提醒條是很重要的。還在文本編輯模式時,修改你的用戶自定義示圖的layout:width屬性爲10dp,layout:height屬性爲match_parent。這裏用的match_parent值將讓這個示圖控件象它的父控件同樣高。切換到設計模式並拖放一個大文本控件到水平線性佈局的元件樹上,並設置寬高屬性爲match_parent。檢查下這個大文本元件定位於用戶自定義示圖控件的右側。在元件樹裏,標誌文本視圖的元件必定是嵌套在水平線性佈局元件裏面而且在示圖元件下面。若是文本視圖在示圖元件上面,把它拖下來放到第二(即最後)的位置。給這個文本視圖一個id值row_text並設置文字尺寸爲18sp。sp這個單位參照像素獨立密度度量系統,象dp那樣,但它尊照用戶的文本尺寸設置,於是好比:若是用戶很難看清並想他的手機上的顯示更大的文字,sp將尊照這個設置,然而dp不會。所以,用sp做爲文字的尺寸單位老是一個好點子。你將在第8章學到有關屏幕度量的更多內容。

Finally, set the TextView control’s text property to Reminder Text. Switch to Text mode and make additional changes to the XML so that your code resembles Listing 5-1.
<翻譯>
最後,設置文本控件的文本屬性爲Reminder Text"。切換到文本編輯模式作更多的修改如清單5-1所示。
清單5-1 reminders_row 佈局XML代碼
Listing 5-1. The reminders_row Layout XML Code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="48dp">
<view
android:layout_width="10dp"
android:layout_height="match_parent"
class="android.view.View"
android:id="@+id/row_tab" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:textAppearance="?
android:attr/textAppearanceLarge"
android:text="Reminder Text"
android:id="@+id/row_text"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>

You will now create some custom colors. Switch to Design mode. Select the root LinearLayout (vertical) in the Component Tree. Set its android:background attribute to @color/dark_grey to reuse the color we defined earlier. Select the row_tab component in the Component Tree and set its android:background attribute to @color/green. Select the
row_text component and set its android:textColor attribute to @color/white. As before, these colors are not defined in the colors.xml file, and you will need to use the same process as before to define them. Switch to Text mode. Press the F2 key repeatedly to jump back and forth between these two additional errors and press Alt+Enter to bring up the IntelliSense suggestion. Choose the second suggestion in both cases and fill in the pop-up dialog box with the values #ffffff for fixing the white color and #003300 to fix the green color. After using the suggestion dialog box to fix these errors, you can hold the Ctrl key and left-click any of these colors which will bring you to the colors.xml file and should look like Listing 5-2.
<翻譯>
如今要建立一些用戶顏色了。切換到設計模式。選擇元件樹線性佈局(垂直方向的)的根。設置android:background屬性爲@color/dark_grey來重用以前所定義的顏色。在元件樹裏選擇row_tab元件並設置它的android:background屬性爲@color/green。選擇row_text元件並設置它的android:textColor屬性爲@color/white。在這以前,這些顏色並沒設置在colors.xml裏,象以前那樣定義它們。切換到到文本模式。按F2在這兩個錯誤間重複地跳前和跳後並按Alt_Enter帶出智能建議。選擇第二個建議並在彈出對話框裏用#ffffff和#003300修正白色和綠色的問題。修正這些問題後,你能夠按Ctrl鍵和左鍵點擊這些顏色將帶到colors.xml文件裏,如清單5-2代碼所示。
Listing 5-2. The colors.xml File
<resources>
<color name="dark_grey">#181818</color>
<color name="white">#ffffff</color>
<color name="green">#003300</color>
</resources>

Return to the activity_reminders.xml layout file. You will now connect the new reminders_row layout to the ListView in this layout. Switch to Text mode and add the following attribute to the ListView element: tools:listitem="@layout/reminders_row" as shown in Figure 5-16.
<翻譯>
回到activity_reminders.xml佈局文件。現連結新的reminders_row佈局到這個佈局了。切換到文本模式並加入現面的屬性到ListView元素裏tools:listitem="@layout/reminders_row",如圖5-16所示。

Adding this attribute doesn’t change the way the layout renders when it runs; it merely changes what the preview pane uses for each item in the list view. To make use of the new layout, you must inflate it using Java code and we will show you how do that in a subsequent step.
<翻譯>
加上這個屬性在運行時並沒改變佈局的表象;它只不過改變這個list view的每一個條目的預覽面板。要讓這個新佈局有用,你必須用JAVA代碼充實它,這個咱們將在後續的章節裏展現給你。


圖5-16 預覽面板現正展現一個用戶自定義的ListView佈局

Adding Visual Enhancements

You have just completed a custom layout for your ListView rows, but you shouldn’t stop there. Adding a few visual enhancements will make your app stand-out from the others. Take a look at how the text renders on-screen. A careful eye will catch how it is slightly off-center and runs up against the green tab on the left. Open the reminders_row layout to make some minor adjustments. You want the text to gravitate toward the vertical center of the row and give a bit of padding so as to provide some visual separation from the side edges. Replace your TextView element with the code in Listing 5-3.
<翻譯>
加入圖形加強
剛剛完成一個ListView條目的用戶自定義佈局,但你不會中止在這裏。加入一些視覺加強元素將讓你的app不同凡響。看一下文本如何顯示在屏幕上。精明點的眼球會看到它有點點偏離中心並跑出綠色選項卡的左邊。打開reminder_row佈局作點小調整。你但願文本重心朝行內垂直方向的中心去點,並給出點邊襯這樣和邊界就有點視覺上的分離。用清單5-3的代碼代替你的TextView元素。
Listing 5-3. TextView Additional Attributes
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Reminder Text"
android:id="@+id/row_text"
android:textColor="@color/white"
android:textSize="18sp"
android:gravity="center_vertical"
android:padding="10dp"
android:ellipsize="end"
android:maxLines="1"
/>

The additional ellipsize attribute will truncate text that is too long to fit in the row with an ellipsis on the end, whereas the maxLines attribute restricts the number of lines in each row to 1. Finally, add two more generic view objects from Listing 5-4 after the inner LinearLayout but before the closing tag of the outer LinearLayout to create a horizontal rule beneath the row. The outer LinearLayout is set to a height of 50dp, and the inner LinearLayout is set to a height of 48dp. The two generic view objects will occupy the remaining vertical 2dp inside the layout creating a beveled edge. This is shown in Listing 5-4.
<翻譯>
增長的省略屬性將截去過長的文本以適應該條目以一個省略號結束,然而maxLines屬性限制了每一個條目的行數爲1。最後,在內部的線性佈局後面但外部線佈局結束以前從清單5-4里加上兩個更普通的示圖對象,來建立條目下的水平規則。外部的線性佈局設置高爲50dp,內部的則設置爲48dp。這兩個通用的view對象將佔用剩下的垂直的2dp空間來建造一個斜邊。清單5-4以下。
Listing 5-4. Extra Generic Views for beveled edge
</LinearLayout>
<view
class="android.view.View"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#000"/>
<view
class="android.view.View"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#333"/>
</LinearLayout>
<譯者注:上面代碼中的控件view會有些問題,沒法解析背景色屬性。最好改爲android.view.View>
<android.view.View
class="android.view.View"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#000"/>
<android.view.View
class="android.view.View"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#333"/>

Adding Items to ListView

You will now make changes to the activity that uses the layout you just modified. Open the Project tool window and find the RemindersActivity file under your java source folder. It will be located under the com.apress.gerber.reminders package. Find the onCreate() method in this file. It should be the first method defined in your class. Declare a ListView member called mListView and change the onCreate() method to look like the code in Listing 5-5. You will need to resolve the imports ListView and ArrayAdapter.
<翻譯>
加載條目到ListView
如今剛修改的佈局將改變activity。打開項目工具窗並在JAVA源代碼文件夾下找到RemindersActivity文件。它位於com.apress.gerber.reminders包裏。找到onCreate()方法。這是你的類裏第一個定義的方法。聲明一個ListView成員變量取名mListView按清單5-5那樣修改onCreate()方法。你將須要解決引入ListView和ArrayAdapter。
Listing 5-5. Add List Items to the ListView
public class RemindersActivity extends ActionBarActivity {
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reminders);
mListView = (ListView) findViewById(R.id.reminders_list_view);
//The arrayAdatper is the controller in our
//model-view-controller relationship. (controller)
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
//context
this,
//layout (view)
R.layout.reminders_row,
//row (view)
R.id.row_text,
//data (model) with bogus data to test our listview
new String[]{"first record", "second record", "third record"});
mListView.setAdapter(arrayAdapter);
}
//Remainder of the class listing omitted for brevity
}

This code looks up the ListView by using the id property you defined earlier and removes the the default list divider so that the custom beveled divider we created earlier will render properly. The code also creates an adapter with a few example list items. Adapter is a special Java class defined as part of the Android SDK that functions as the Controller in the Model-View-Controller relationship among the SQLite database (Model), the ListView (View), and the Adapter (Controller). The Adapter binds the Model to the View and handles updates and refreshes. Adapter is the superclass of ArrayAdapter, which binds elements of an Array to a View. In our case, this View is a ListView. ArrayAdapter takes three parameters in its three-argument constructor. The first parameter is a Context object represented by the current activity. The Adapter also needs to know which layout and which field, or fields, in the layout should be used to display row data. To satisfy this requirement, you pass the ids of both the layout and the TextView item in the layout. The last parameter is an array of Strings used for each item in the list. If you run the project at this point, you will see the values
given in the ArrayAdapter constructor displayed in the list view as seen in Figure 5-17.
<翻譯>
代碼裏用你早先定義id屬性查找ListView控件,而且去除了默認的條目分隔器,這樣咱們早先自定義的帶斜邊分隔器將會很好地渲染。這些代碼也建立了一個帶有幾個例子條目的適配器。適配器是一種特別的JAVA類定義於Android SDK裏,它的功能做爲在SQLite數據庫(模型)裏模型-示圖-控制器關係的控制器,ListView(示圖),還有適配器(控制器)。適配器綁定模型到示圖上而且處理更新和刷新。Adapter是ArrayAdapter的超類,用來綁定數組到示圖裏。在咱們的例子裏,這個示圖是ListView。ArrayAdapter的構造函數有三個參數。第一個是上下文對象用來表達當前activity。適配器也須要知道那個佈局和佈局裏的區域或多個區域用於顯示行數據。爲知足這個要求,你要傳送佈局和文本示圖條目的id到佈局裏。最後一個參數是一個字符串數組用於表裏的每一個條目。若是你這時運行項目,將看到給到ArrayAdapter構造器的那些值顯示如圖5-17。


圖5-17 ListView例子

Press Ctrl+K | Cmd+K to commit your changes to Git and use Adds ListView with custom colors as the commit message. As you work through a project, it is good practice to perform incremental commits to Git while using commit messages that describe the features each commit adds/removes/changes. Keeping this habit makes it easy to identify individual commits and later build release notes for future collaborators and users.
<翻譯>
按Ctrl+K | Cmd+K提交更改到Git並填入Adds ListView with custom colors到提交信息裏。當你工做於這個項目裏,用提交信息描述每次提交的追加/移除/更改來執行增長提交到Git是一個不錯的體驗。爲未來的合做者及用戶保持這個習慣來會讓事情變得容易點,來鑑別各次單獨的提交以及之後的構建記錄。

Setting the Action Bar Overflow Menu

Android uses a common visual element called Action Bar. The Action Bar is where many apps locate navigation and other options that allow the user to perform important tasks. When you run the app at this point, you may notice a menu icon that looks like three vertical dots. These dots are known as the overflow menu. Clicking the overflow menu
icon produces a menu with a single menu item entry called settings. This menu item is placed there as part of the new project wizard template and is essentially a placeholder that performs no action. The RemindersActivity loads the menu_reminders.xml file, which is found under the res/menu folder. Make changes to this file to add new menu items to the activity as seen in Listing 5-6.
<翻譯>
設置溢出菜單的行爲條
Android使用一個共同的可視化元素叫作行爲條。行爲條用於多數app定位導航和其餘選項以讓用戶執行重要的任務。這時運行這個app,你可能注意到一個菜單圖標象三個豎直點的那個。這些點被叫作溢出菜單。點擊這個溢出菜單圖標會產生只有一個叫setting菜單項的菜單。這個菜單項放在那是新項目嚮導模板的一部分而且本質上是一個佔位沒有任何執行動做。RemindersActivity裝載了menu_reminders.xml文件,能夠在res/menu文件夾下找到。讓咱們象清單5-6那樣對這個文件作點改變加上一些新的菜單項。
Listing 5-6. New Menu Items
<menu xmlns:android=" http://schemas.android.com/apk/res/android"
xmlns:app=" http://schemas.android.com/apk/res-auto"
xmlns:tools=" http://schemas.android.com/tools"
tools:context="com.apress.gerber.reminders.app.RemindersActivity" >
<item android:id="@+id/action_new"
android:title="new Reminder"
android:orderInCategory="100"
app:showAsAction="never" />
<item android:id="@+id/action_exit"
android:title="exit"
android:orderInCategory="200"
app:showAsAction="never" />
</menu>

In the preceding code listing, the title attribute corresponds to the text displayed in the menu item. Since we’ve hard-coded these attributes, Android Studio will flag these values as warnings. Press F2 to jump between these warnings and press Alt+Enter to pull up the IntelliSense suggestions. You simply need to press Enter to accept the first suggestion, type a name for the new String resource, and as soon as the dialog box pops-up, press Enter again to accept the named resource. Use new_reminder for the name of the first item and exit for the second.
<翻譯>
在前述的代碼清單裏,title屬性關聯於菜單項的顯示文本。由於咱們用硬代碼設置這些屬性值,Andorid Studio將會標記警告。按F2在這些警告間跳躍並按Alt+Enter拉出智能建議。你只需簡單地按回車接受第一個建議,輸入新字符串資源的名稱,接着立刻彈出對話框,再按回車接受命名的資源。用new_reminder做爲第一個條目的名稱,第二個叫exit。

Open RemindersActivity and replace the onOptionsItemSelected() method with the text in Listing 5-7. You will need to resolve the import for the Log class. When you tap a menu item in the app, the runtime invokes this method, passing in a reference to whichever MenuItem was tapped. The switch statement takes the itemId of the MenuItem and either performs a log statement or terminates the activity, depending on which item was tapped. This example uses the Log.d() method that writes text to the Android debug logs. If your app contained multiple activities and those activities were viewed prior to the current activity, then calling finish() would simply pop the current activity off the backstack and control would pass to the next underlying activity. Because the RemindersActivity is the only activity in this app, the finish() method pops the one and only activity off the backstack and results in the termination of your app.
<翻譯>
打開RemindersActivity並用清單5-7的代碼代替onOptionItemSelected()方法。你還須要解決Log類的引入。當你點擊app上的一個菜單項時,實時調用這個方法,傳入那個被點擊的菜單項的引用。Switch語句用MenuItem的itemId,執行一個log語句或終結這個activity,取決於哪一個菜單項被點擊了。這個例子用Log.d()方法寫入文本到Android的調試日誌裏。若是你的app包括多個activity而且這些activity比當前activity先顯示,那麼調用finish()將簡單地把當前activity推出棧而且把控制交給下面的activity。由於RemindersActivity是這個app的惟一activity,finish()方法推出它將致使這個app的終止。
Listing 5-7. onOptionsItemSelected( ) Method Definition
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_new:
//create new Reminder
Log.d(getLocalClassName(),"create new Reminder");
return true;
case R.id.action_exit:
finish();
return true;
default:
return false;
}
}

Run the app and test the new menu options. Tap the new Reminder menu option and watch the Android log to see the message appear. The Android DDMS (Dalvik Debug Monitor Service) window will open as you run your app on your emulator or device, and you will need to select the Debug option under Log Level to see debug logs. Run your app and interact with the menu items. Pay attention to the logs in the Android DDMS window as you tap the New Reminder menu item. Finally, press Ctrl+K | Cmd+K and commit your code to Git using Adds new reminder and exit menu options as your commit message.
<翻譯>
運行這個app並測試新的菜單選項。點擊new Reminder菜單項並觀察Android日誌裏出現的信息。Android DDMS(Dalvik調試監控服務)窗將與仿真器或設備運行app的同時打開,而且你將須要選擇調試選項低於Log級別纔可看到調試日誌。運行你的app並與這些菜單項互動。注意在你點擊New Reminder菜單項時Android DDMS出來的日誌。最後,按Ctrl+K | Cmd+K並提交你的代碼到Git,用Adds new reminder and exit menu options做爲提交信息。

Persisting Reminders

Because the Reminders app will need to maintain a list of reminders, you will need a persistence strategy. The Android SDK and runtime provide an embedded database engine called SQLite, which is designed to operate in constrained memory environments and is well suited for mobile devices. This section covers the SQLite database and explores how to maintain a list of reminders. Our strategy will include a data model, a database proxy class, and a CursorAdapter. The model will hold the data that is read from and written to the database. The proxy will be an adapter class that will translate simple calls from the app into API calls to the SQLite database. Finally, the CursorAdapter will extend a standard Android class that deals with data access in an abstract way.
<翻譯>
保持提醒
由於Reminders這個app須要保存提醒清單,你將須要一個保存策略。Android SDK和運行時系統提供了一個內建的數據庫引擎叫SQLite,它設計爲有限記憶體環境並很適合於移動設備。這節涵括了SQLite數據庫並瀏覽怎麼保存提醒清單。咱們的策略將包括一個數據模型,一個數據庫代理類,還有一個遊標適配器(CursorAdapter)。這個模型將維持數據讀寫到數據庫。代理將是一個適配器類將把從app簡單調用轉換爲到數據庫API調用。最後,遊標適配器將擴展爲一個標準的Android類用於以抽象方式處理數據訪問。

Data Model

Let’s start by creating the data model. Right click the com.apress.gerber.reminders package and select New ➤ Java Class. Name your class Reminder and press Enter. Decorate your class with the code in Listing 5-8. This class is a simple POJO (Plain Old Java Object) that defines a few instance variables and corresponding getter and setter
methods. The Reminder class includes an integer ID, a String value, and a numeric importance value. The ID is a unique number used to identify each reminder. The String value holds the text for the reminder. The importance value is a numeric indicator that flags an individual reminder as important (1 = important, 0 = not important). We used int
rather than boolean here because the SQLite database does not have a boolean datatype.
<翻譯>
數據模型
讓咱們開始建立數據模型。右擊com.apress.gerber.reminders包並選擇New ➤ Java Class。命名這個類爲Reminder並按回車。如清單5-8那樣裝裱這個類。這是一個簡單的POJO(簡單的老JAVA對象)定義了幾個實例變量和相應的getter及setter方法。Remider類包含了和個整型的ID,字符串變量,和數值化的重要值。ID是用於標記每一個提醒的惟一數字。字符串則保存了提醒的文本。重要值是一個數值化的指示器用來標誌一個獨立的提醒是否重要(1=重要,0=不重要)。咱們更願意用整型而不是布爾值是由於SQLite數據庫沒有布爾數據類型。
Listing 5-8. Reminder Class Definition
public class Reminder {
private int mId;
private String mContent;
private int mImportant;
public Reminder(int id, String content, int important) {
mId = id;
mImportant = important;
mContent = content;
}
public int getId() {
return mId;
}
public void setId(int id) {
mId = id;
}
public int getImportant() {
return mImportant;
}
public void setImportant(int important) {
mImportant = important;
}
public String getContent() {
return mContent;
}
public void setContent(String content) {
mContent = content;
}
}

Now you will create a proxy to the database. Again, this proxy will translate simple application calls into lower-level SQLite API calls. Create a new class in your com.apress. gerber.reminders package called RemindersDbAdapter. Place the code in Listing 5-9 directly inside of your newly created RemindersDbAdapter class. As you resolve imports,
you will notice that DatabaseHelper is not found in the Android SDK. We will define the DatabaseHelper class in a subsequent step. This code defines the column names and indices; a TAG for logging; two database API objects; some constants for the database name, version, and the main table name; the context object; and a SQL statement used to create the database.
<翻譯>
如今你將建立一個數據代理。再次,這個代理將轉換簡單的應用調用爲低級別的SQLite API調用。在com.apress.gerber.reminders包裏新建一個類叫RemindersDbAdapter。把清單5-9的代碼直接加入到這個新類裏。當你解析導入時,發現DatabaseHelper並沒在Android SDK裏。咱們將在後面的步驟裏定義DatabaseHelper。這些代碼定義了列名稱和索引;一個TAG做日誌;兩個上下文對外對象;和一個SQL語句用於建立數據庫。
Listing 5-9. Code to be placed inside the RemindersDbAdapter class
//these are the column names
public static final String COL_ID = "_id";
public static final String COL_CONTENT = "content";
public static final String COL_IMPORTANT = "important";
//these are the corresponding indices
public static final int INDEX_ID = 0;
public static final int INDEX_CONTENT = INDEX_ID + 1;
public static final int INDEX_IMPORTANT = INDEX_ID + 2;
//used for logging
private static final String TAG = "RemindersDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private static final String DATABASE_NAME = "dba_remdrs";
private static final String TABLE_NAME = "tbl_remdrs";
private static final int DATABASE_VERSION = 1;
private final Context mCtx;
//SQL statement used to create the database
private static final String DATABASE_CREATE =
"CREATE TABLE if not exists " + TABLE_NAME + " ( " +
COL_ID + " INTEGER PRIMARY KEY autoincrement, " +
COL_CONTENT + " TEXT, " +
COL_IMPORTANT + " INTEGER );";

SQLite API

DatabaseHelper is a SQLite API class used to open and close the database. It uses Context, which is an abstract Android class that provides access to the Android operating system. DatabaseHelper is a custom class, and must be defined by you. Use the code in Listing 5-10 to implement DatabaseHelper as an inner class of RemindersDbAdapter. Place this proceeding code towards the end of the RemindersDbAdatper but still inside RemindersDbAdapters enclosing braces. <翻譯> SQLite API DatabaseHelper是一個SQLite API類,用於打開和關閉數據庫。它用到了上下文Context,這是一個抽象的Android類以提供到Android操做系統的訪問。DatabaseHelper是一個用戶自定義類,且必須由你來定義。用清單5-10實施DatabaseHelper類,做爲RemindersDbAdapter的內部類。把這些代碼放到RemindersDbAdapter後段,但在類結束的花括號的前面。 Listing 5-10. RemindersDbAdapter private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { Log.w(TAG, DATABASE_CREATE); db.execSQL(DATABASE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } DatabaseHelper extends SQLiteOpenHelper, which helps maintain the database with special callback methods. Callback methods are methods that the runtime environment will call throughout the life-cycle of the application, and they use the SQLiteDatabase db variable supplied to execute SQL commands. The constructor is where the database is initialized. The constructor passes the database name and version to its superclass; and then the superclass does the hard work of setting up the database. The onCreate() method is called automatically by the runtime when it needs to create the database. This operation runs only once, when the app first launches and the database has not yet been created. The onUpgrade() method is called whenever the database needs to be upgraded, for example if the developer changes the schema. If you do change the database schema, be sure to increment the DATABASE_VERSION by one, and onUpgrade() will manage the rest. If you forget to increment the DATABASE_VERSION, your app will crash even in debug build mode. In the preceding code, we run a SQL command to drop the one and only table in the database before running the onCreate() method to re-create the table. <翻譯> DatabaseHelper 繼承於QLiteOpenHelper,用於以特殊的回調方法來維護數據庫。回調方法是運行時環境在應用的整個生命週期內都調用的方法,而且它們用到SQLiteDatabase db變量提供SQL命令的執行。在構造器裏數據庫就被初始化了。構造器傳遞數據庫名和版本到它的父類;而後父類作數據庫的設置繁雜工做。當須要創建數據庫時onCreate()方法被運行時自動調用。這個操做只運行一次,當app首次啓動而且數據庫還未建立時。onUpgrade()方法是在數據庫更新時被調用,例如假如開發者改變綱要。若是你改變數據庫的綱要,確保給DATABASE_VERSION增長1,而後onUpgrade()會處理剩下的事情。若是你忘了給DATABASE_VERSION加1,你的app將崩潰即使在調試構建模式下。在前述的代碼裏,在運行onCreate()方法以前咱們運行一個SQL命令來移除數據庫裏惟一的表單,以方便重建表單。 The code in Listing 5-11 demonstrates using DatabaseHelper to open and close the database. The constructor saves an instance of Context, which is passed to DatabaseHelper. The open() method initializes the helper and uses it to get an instance of the database, while the close() method uses the helper to close the database. Add this code after all the member variable definitions and before the DatabaseHelper inner class definition inside the RemindersDbAdapter class. When you resolve imports, use the android.database.SQLException class. <翻譯> 清單5-11演示了用DatabaseHelper來打開和關閉數據庫。構造器保存了上下文的一個實例,它會被傳送到DatabaseHelper。open()方法初始化helper並用它獲得一個數據庫的實例,直到close()方法用於關閉數據庫。把這些代碼加入到RemindersDbAdapter類裏,在全部成員變量以後和DatabaseHelper內部類以前。當你解析導入時,用android.database.SQLException類。 Listing 5-11. Database Open and Close Methods public RemindersDbAdapter(Context ctx) { this.mCtx = ctx; } //open public void open() throws SQLException { mDbHelper = new DatabaseHelper(mCtx); mDb = mDbHelper.getWritableDatabase(); } //close public void close() { if (mDbHelper != null) { mDbHelper.close(); } } Listing 5-12 contains all the logic that handles the creating, reading, updating, and deleting of Reminder objects in the tbl_remdrs table. These are usually referred to as CRUD operations; CRUD stands for create, read, update, delete. Add the proceeding code after the close() method inside the RemindersDbAdapter class. <翻譯> 清單5-12包含了全部處理在tbl_remdrs表單裏建立,讀取,更新,和刪除Reminder對象的操做。一般參考CRUD操做;CRUD即表明建立,讀取,更新,刪除。加入這些代碼到RemindersDbAdapter類的close()方法以後。 Listing 5-12. Database CRUD Operations //CREATE //note that the id will be created for you automatically public void createReminder(String name, boolean important) { ContentValues values = new ContentValues(); values.put(COL_CONTENT, name); values.put(COL_IMPORTANT, important ? 1 : 0); mDb.insert(TABLE_NAME, null, values); } //overloaded to take a reminder public long createReminder(Reminder reminder) { ContentValues values = new ContentValues(); values.put(COL_CONTENT, reminder.getContent()); // Contact Name values.put(COL_IMPORTANT, reminder.getImportant()); // Contact Phone Number // Inserting Row return mDb.insert(TABLE_NAME, null, values); } //READ public Reminder fetchReminderById(int id) { Cursor cursor = mDb.query(TABLE_NAME, new String[]{COL_ID, COL_CONTENT, COL_IMPORTANT}, COL_ID + "=?", new String[]{String.valueOf(id)}, null, null, null, null ); if (cursor != null) cursor.moveToFirst(); return new Reminder( cursor.getInt(INDEX_ID), cursor.getString(INDEX_CONTENT), cursor.getInt(INDEX_IMPORTANT) ); } public Cursor fetchAllReminders() { Cursor mCursor = mDb.query(TABLE_NAME, new String[]{COL_ID, COL_CONTENT, COL_IMPORTANT}, null, null, null, null, null ); if (mCursor != null) { mCursor.moveToFirst(); } return mCursor; } //UPDATE public void updateReminder(Reminder reminder) { ContentValues values = new ContentValues(); values.put(COL_CONTENT, reminder.getContent()); values.put(COL_IMPORTANT, reminder.getImportant()); mDb.update(TABLE_NAME, values, COL_ID + "=?", new String[]{String.valueOf(reminder.getId())}); } //DELETE public void deleteReminderById(int nId) { mDb.delete(TABLE_NAME, COL_ID + "=?", new String[]{String.valueOf(nId)}); } public void deleteAllReminders() { mDb.delete(TABLE_NAME, null, null); } Each of these methods uses the SQLiteDatabase mDb variable to generate and execute SQL statements. If you are familiar with SQL, you may guess that these SQL statements will be in the form of an INSERT, SELECT, UPDATE, or DELETE. <翻譯> 每一個方法都用到了SQLiteDatabase mDb變量來生成和執行SQL語句。若是你熟悉SQL,你會猜到這些SQL語句將由INSERT, SELECT, UPDATE, 或 DELETE組成。 The two create methods use a special ContentValues object, which is a data shuttle used to pass data values to the database object’s insert method. The database will eventually convert these objects into SQL insert statements and execute them. There are two read methods, one for fetching a single reminder and another for fetching a cursor to iterate all reminders. You will use Cursor later in a special Adapter class. <翻譯> 兩個建立方法用到了特別的ContentValues對象,這個是數據載體用於在insert方法裏傳送數據值到數據庫對象。在insert語句裏數據庫最終將轉換這些對象到數據庫。有兩個讀方法,一個用於引出單個提醒另外一個則引出一個遊標以遍歷全部的提醒。晚點在一個特別的Adapter類裏你將用到遊標。 The update method is similar to the second create method. However, this method calls an update method on the lower-level database object, which will generate and execute an update SQL statement rather than an insert. <翻譯> 更新方法象第二個建立方法。不管怎樣,這個方法調用了底層的數據庫對象的更新方法,那個將生成並執行一個更新SQL語句而不是一個插入語句。 Last, there are two delete methods. The first takes an id parameter and uses the database object to generate and execute a delete statement for a particular reminder. The second method requests that the database generate and execute a delete statement to remove all the reminders from the table. <翻譯> 最後,有兩個刪除方法。第一個針對特定的提醒用 id參數和數據庫對象來生成和執行一條刪除語句。第二個方法須要數據庫生成並執行一條刪除語句來移除全部表單裏的提醒。 At this point, you need a means of getting reminders out of the database and into the ListView. Listing 5-13 demonstrates the logic necessary to bind database values to individual row objects by extending the special Adapter Android class you saw earlier. Create a new class c
相關文章
相關標籤/搜索