<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 第五章:Reminders實驗:第一部分 > 譯者:[qiangxcn](http://ask.android-studio.org/?/people/qiangxcn) > 來源: > + [Learn Android Studio 漢化教程 第五章:Reminders實驗:第一部分](http://ask.android-studio.org/?/question/947) > + [Learn Android Studio 漢化教程 第五章:Reminders實驗:第一部分(續)](http://ask.android-studio.org/?/question/978) 到現在為止你已經熟悉了創建一個新項目,編程,和重構的基本操作了。是時候創建一個Android 應用了,或者說成我們所謂的APP。這章將介紹四個實例項目的第一個。這些實例目的是讓你熟悉使用Android Studio開發APP的上下文方面。核心功能是允許你創建和刪除一個提醒以及標志那些重要的提醒。重要的條目文體左邊將被強調黃色標簽。這個APP將合同一個動作條菜單,上下文菜單,一個本地的數據庫作存儲,如果設備支持的話還有多重選擇。 圖5-1圖示了仿真器上完成的app。這個例子介紹了Android基礎并且你也會學到如何用內建的SQLite數據庫來保存數據。別擔心那些你不熟悉的話題,后續的章節將涵括這些話題大量的細節。 注意:為了一致性,我們建議你用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`。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c38386b.png) 圖5-1 完成的app界面 操作Reminders這個app,你可以用動作條的溢出菜單。點擊溢出按鈕,在菜單欄右側,看起來象垂直點,打開一個菜單如圖5-2有兩個選項:新提醒,和退出。點擊新提醒打開一個對話框如圖5-3。在這個對話框里,你可以為新提醒加入文本并且點提交加到清單里。點擊退出。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c3a0c8a.png) 圖5-2 激活溢出菜單的app界面 ![](https://box.kancloud.cn/2016-08-06_57a5d3c3bec50.png) 圖5-3 新提醒對話框 點擊清單中的隨意一個提醒有兩個可選方式,如圖5-4:編輯提醒和刪除提醒。從上下文菜單中點編輯提醒,彈出對話框如圖5-5所示,在那里你可以修改提醒里的文本。點擊刪除提醒則會刪掉這個提醒。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c3e8021.png) 圖5-4 上下文菜單 ![](https://box.kancloud.cn/2016-08-06_57a5d3c40ede1.png) 圖5-5 編輯提醒對話框 ## 開始一個新項目 在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所示。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c432024.png) 圖5-6 輸入`activity`名稱 Android Studio在設計模式下顯示`activity_reminder.xml`。這是你的主`activity`的布局,如圖5-7示。如同第1章所討論的,在這刻項目可以運行在仿真器上或設備上。只要你樂意隨便用哪個。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c456845.png) 圖5-7 `activity_reminders`的設計模式 ## 初始化Git存儲庫 建立新項目后的第一步必須是用版本控制來管理源代碼。所有這本書的例子都用Git,一個流行的版本控制系統,無縫地協同Android Studio工作并且一直是在線免費的。第7章更徹底地探索了Git和版本控制。 如果你還沒安裝Git,請參考第7章。從主菜單選擇`VCS>Import into Version Control>Create Git Repository`。(在IOS上,選擇`VCS >VCS Operations>Create Git Repository`)圖5-8和5-9展示了這個流程。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c47f980.png) 圖5-8 創建一個Git存儲庫 ![](https://box.kancloud.cn/2016-08-06_57a5d3c4a1266.png) 圖5-9 為Git存儲庫選擇根目錄 當提示選擇Git的初始目錄,確認初始化為項目的根目錄(再次,在這個例子里是Reminders)。點擊OK。 你將注意到項目工具窗里大部分文件變成棕色的,意味著它們被Git跟蹤但還沒加入到Git的存儲庫而且時刻表也沒加載。一但你的項目被Gitr控制,Android Studio使用一個色彩策略,隨著我們項目的進行將會解釋更多的細節。當然你也可能在這: jetbrains.com/idea/help/file-status-highlights.html 得更多的細節,如果你想研究的話。 點擊位于窗口底部邊緣的Changes工具按鈕切換打開Changes工具窗口并展開葉子標簽的未受版本控制文件。這將顯示所有被跟蹤的文件。為加載它們,選擇未受版本控制文件葉子并按`Ctrl+Alt+A | Cmd+Alt+A`或右擊未受版本控制文件葉子并選擇`Git>Add`。棕色文件將會變成綠色,意味著它們在Git中已階段化而且現在準備被提交了。 按`Ctrl+K | Cmd+K`來調用提交更改對話框。提交文件是Git版本控制系統記錄項目更改的一個過程。如圖5-10所示,授權者下拉菜單用于重寫當前缺省提交者。讓這欄空著吧,這樣Android Studio將簡單地用你安裝Git時設的缺省值。去選Before Commit多選框里所有的選項。把下面的信息放入到Commit Message區里:Initial commit using new project wizard。點擊提交按鈕并在下拉條目里再次選擇提交。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c4c160b.png) 圖5-10 提交更改到Git 默認情況下,項目工具窗將會打開。項目工具窗以不同的方式組織你的項目,取決于頂部窗口的下拉菜單所選擇的示圖。缺省地,下拉菜單是Android示圖,它按文件目的組織文件而不是按你電腦操作系統組織文件的方式。當你展開項目工具窗,將注意到三個文件夾在app文件夾下:manifests, java, 和 res。Manifests文件夾里有你的Android manifest文件。Java文件夾是存放java 源文件的地方。Res文件夾保存所有你的Android資源文件。在res目錄下的資源可能是XML文件,圖象,聲音,和其他資源用于幫助定義你的app外觀和用戶體驗。一但你有機會展開Android示圖,我們推薦切換到Project示圖,它更直觀因為它直接反映了你電腦上的目錄結構。 ## 構建用戶界面 默認情況下,Android Studio打開與主`activity`相關聯的XML布局文件在一個新的編輯選項卡里并設置為設計模式,因而通常你在新項目里先看到的是可視化開發器。可視化開發器讓你編輯app的可視化布局。在屏幕的中央是預覽面板。預覽面板是Android設備渲染你當前編輯的布局結果的虛擬展示。這個展示可控于屏幕上方橫跨的布局預覽控制。這些控制可調整預覽并選擇不同風格的Android設備,從智能電話到穿戴設備。你也可以改變布局里所描述的相關主題。屏幕的左邊,你會發現控件板。包含了眾多的控件和`widget`,它們可被拖放到正虛擬展示的設備平臺上。IDE的右側包含了一個組件樹展示了布局里組件的層次關系。布局使用XML文件。當你在這個可視化開發器作出修改時,這些修改將更新于XML中。你可選擇Design或Text選項卡來切換可視化或是文本編輯模式。圖5-11標識幾個可視化開發器關鍵區域。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c4e4aa9.png) 圖5-11 可視化開發器界面 ## 工作于圖形化編輯器 讓我們開始創建reminders的列表項吧。在平臺上點擊`Hello World`文本框并刪除它。找到`ListView`控件并拖放到平臺里。當你拖動時,IDE將顯示變化著的尺寸度量以及排列參考來幫助你定們控件,那些當你拖動靠近它們時會企圖抓住邊緣。拖放`listView`它會在屏幕頂部排列。你可以定位在頂部的左邊或中間。在定位后,找到在編輯器右下側的屬性示圖。設置`id`屬性為`reminders_list_view`。`Id`屬性是你可以在JAVA代碼里控件編程參考;且這個是我們將如何參考的ListView在之后修改代碼時。修改`layout:width`屬性設置為`match_parent`。這將擴展控件動態地占有盡可能多的父控件寬度。關于布局在第8章里你會學到更多細節。現在,你的布局將裝配成圖5-12那樣。 ![](img/5-12.png) 圖5-12 有個`ListView`的`activity_reminders`的布局 在Android里,一個`activity`定義了控制用戶和app交互的邏輯。當第一次學Android時,把`activity`想象成你的app的一個屏幕是對你有幫助的,雖然`activity`要比這個復雜得多。布局文件定義為一個XML,但用早先提到的圖形化編輯器可以圖形化編輯。 ## 編輯布局的原生XML 點擊編輯器左下方的文本選項卡,從圖形化編輯切換到文本編輯模式。這帶來了布局的原生XML示圖,右邊伴隨著一個預覽面板。將`RelativeLayout`的背景色改為黑色,插入這行:`android:background="#181818" `到`android:layout_height="match_parent"`下面。顏色用十六進制來表達。可以看下第9章關于十六進制顏色的更多信息。注意到你插入那條設置根示圖背景色那行后夾縫里的黑灰色的樣本。如果你回到設計模式,會觀察到整個布局變成黑灰色了。 直接用硬編碼一個顏色值到你的XML文件里不是最好的途徑。更好的選擇是定義一個`colors.xml`文件到資源文件夾里,并在那定義你的顏色。在XML文件(如`colors.xml`)里實現值的原因是那些資源被保存和編輯在一個地方并且在在整個項目里可以輕松地參考。 用`Ctrl+X | Cmd+X` 或通過主菜單的 `Edit ? Cut`選擇十六進制的顏色值`#181818`并剪切它到粘貼板。輸入`@color/dark_grey`到這個位置。這是一個特殊的語法參考到Android資源文件`colors.xml`,但這個文件還不存在于你的項目里,Android Studio會高亮紅色指出這個錯誤。按`Alt+Enter`會提示糾正這個錯誤的選項。選擇第二個選項,創建顏色資源`dark_grey`,接著把剛才的顏色值粘貼到資源值里:下個出現的對話框值域并點擊OK。 新顏色值資源對話框將創建Android資源文件`colors.xml`并填充十六進制的值。點擊OK接著在加入文件到Git對話框里還是點OK,這個新文件加入到版本控制,并確保選擇Remember,Don’t Ask Again這個復選框因而這個信息下次不會再打擾你了。圖5-13演示了這個流程。 ![](img/5-13-1.png) ![](img/5-13-2.png) 圖5-13 析出硬代碼顏色值到一個資源文件 在預覽模式下這個`ListView`控件包含的行布局在我們所選的背景色時沒有足夠的對比度。要改變這項表象,你將在另外一個布局文件里定義該布局。右擊資源文件夾里的布局文件夾并選擇`New ? Layout Resource File`。在新資源文件對話框里輸入`reminders_row`。在根示圖組里用線性布局并讓其他的為默認值,如圖5-14所示。 ![](img/5-14.png) 圖5-14 新資源文件對話框 你現在將創建列表項獨立的布局。線性布局的根示圖組在布局里是最外層的元素。在預覽面板頂部的工具欄控制鈕設置其走向為垂直方向。當你用這個控制鈕時小心點,因為水平線條表示的是垂直方向,反之亦然。圖5-15高亮了這個走向按鈕。 ![](img/5-15.png) 圖5-15 修改走向按鈕 在預覽面板的右下方找到屬性示圖。找到`layout:height`屬性并設為`50dp`。這個控制控件的高度,`dp`這個單位參照像素獨立密度度量系統。這是公開的,Android允許布局參照屏幕重繪時的密度合適地縮放。你可以點擊這個示圖里的任意屬性并增量鍵入搜索屬性,并按上下鍵繼續搜索。 放一個水平線性布局到垂直線性布局里。拖放一個自定義控件到水平線性控件里并設置它的類屬性為`android.view.View`,來創建一個通用的空示圖并付予`id`為`row_tab`。在寫這篇文章時,Android Studio還是有點局限:它不允許你從控件板里拖放通用示圖。當你點擊`CustomView`時,將得到一個有不同選項的對話框,沒有一個包括了通用的`View`類。選擇任意一個類并放到你的布局里。為這個限制的情況找到類屬性并修改為`android.view.View`。對照清單5-1看看如何完成它 你將會用到這個通用的`View`選項卡來標記那些提醒條是很重要的。還在文本編輯模式時,修改你的用戶自定義示圖`的layout:width`屬性為`10dp`,`layout:height`屬性為`match_paren`t。這里用的`match_parent`值將讓這個示圖控件象它的父控件一樣高。切換到設計模式并拖放一個大文本控件到水平線性布局的元件樹上,并設置寬高屬性為`match_parent`。檢查下這個大文本元件定位于用戶自定義示圖控件的右側。在元件樹里,標志文本視圖的元件一定是嵌套在水平線性布局元件里面并且在示圖元件下面。如果文本視圖在示圖元件上面,把它拖下來放到第二(即最后)的位置。給這個文本視圖一個id值row_text并設置文字尺寸為`18sp`。`sp`這個單位參照像素獨立密度度量系統,象`dp`那樣,但它尊照用戶的文本尺寸設置,因而比如:如果用戶很難看清并想他的手機上的顯示更大的文字,`sp`將尊照這個設置,然而`dp`不會。因此,用`sp`作為文字的尺寸單位總是一個好點子。你將在第8章學到有關屏幕度量的更多內容。 最后,設置文本控件的文本屬性為`"Reminder Text"`。切換到文本編輯模式做更多的修改如清單5-1所示。 清單5-1 `reminders_row` 布局XML代碼 ```xml <?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> ``` 現在要創建一些用戶顏色了。切換到設計模式。選擇元件樹線性布局(垂直方向的)的根。設置`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 ```xml <resources> <color name="dark_grey">#181818</color> <color name="white">#ffffff</color> <color name="green">#003300</color> </resources> ``` 回到`activity_reminders.xml`布局文件。現連結新的`reminders_row`布局到這個布局了。切換到文本模式并加入現面的屬性到`ListView`元素里`tools:listitem="@layout/reminders_row"`,如圖5-16所示。 加上這個屬性在運行時并沒改變布局的表象;它只不過改變這個`list view`的每個條目的預覽面板。要讓這個新布局有用,你必須用JAVA代碼充實它,這個我們將在后續的章節里展示給你。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c525e8b.png) 圖5-16 預覽面板現正展示一個用戶自定義的`ListView`布局 ## 加入圖形增強 剛剛完成一個`ListView`條目的用戶自定義布局,但你不會停止在這里。加入一些視覺增強元素將讓你的app與眾不同。看一下文本如何顯示在屏幕上。精明點的眼球會看到它有點點偏離中心并跑出綠色選項卡的左邊。打開`reminder_row`布局做點小調整。你希望文本重心朝行內垂直方向的中心去點,并給出點邊襯這樣和邊界就有點視覺上的分離。用清單5-3的代碼代替你的`TextView`元素。 Listing 5-3. TextView Additional Attributes ```xml <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" /> ``` 增加的省略屬性將截去過長的文本以適應該條目以一個省略號結束,然而`maxLines`屬性限制了每個條目的行數為1。最后,在內部的線性布局后面但外部線布局結束之前從清單5-4里加上兩個更普通的示圖對象,來創建條目下的水平規則。外部的線性布局設置高為`50dp`,內部的則設置為`48dp`。這兩個通用的view對象將占用剩下的垂直的`2dp`空間來建造一個斜邊。清單5-4如下。 Listing 5-4. Extra Generic Views for beveled edge ```xml <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> <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"/> ``` > 譯者注:上面代碼中的控件`view`會有些問題,無法解析背景色屬性。最好改成`android.view.View` ## 加載條目到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 ```java 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 } ``` 代碼里用你早先定義`id`屬性查找`ListView`控件,并且去除了默認的條目分隔器,這樣我們早先自定義的帶斜邊分隔器將會很好地渲染。這些代碼也創建了一個帶有幾個例子條目的適配器。適配器是一種特別的JAVA類定義于Android SDK里,它的功能作為在SQLite數據庫(模型)里模型-示圖-控制器關系的控制器,`ListView`(示圖),還有適配器(控制器)。適配器綁定模型到示圖上并且處理更新和刷新。`Adapter`是`ArrayAdapter`的超類,用來綁定數組到示圖里。在我們的例子里,這個示圖是`ListView`。`ArrayAdapter`的構造函數有三個參數。第一個是上下文對象用來表達當前`activity`。適配器也需要知道那個布局和布局里的區域或多個區域用于顯示行數據。為滿足這個要求,你要傳送布局和文本示圖條目的`id`到布局里。最后一個參數是一個字符串數組用于表里的每個條目。如果你這時運行項目,將看到給到`ArrayAdapter`構造器的那些值顯示如圖5-17。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c55e329.png) 圖5-17 ListView例子 按`Ctrl+K | Cmd+K`提交更改到Git并填入Adds ListView with custom colors到提交信息里。當你工作于這個項目里,用提交信息描述每次提交的追加/移除/更改來執行增加提交到Git是一個不錯的體驗。為將來的合作者及用戶保持這個習慣來會讓事情變得容易點,來鑒別各次單獨的提交以及以后的構建記錄。 ## 設置溢出菜單的行為條 Android使用一個共同的可視化元素叫做行為條。行為條用于多數app定位導航和其他選項以讓用戶執行重要的任務。這時運行這個app,你可能注意到一個菜單圖標象三個豎直點的那個。這些點被叫做溢出菜單。點擊這個溢出菜單圖標會產生只有一個叫`setting`菜單項的菜單。這個菜單項放在那是新項目向導模板的一部分并且本質上是一個占位沒有任何執行動作。`RemindersActivity`裝載了`menu_reminders.xml`文件,可以在`res/menu`文件夾下找到。讓我們象清單5-6那樣對這個文件做點改變加上一些新的菜單項。 Listing 5-6. New Menu Items ```xml <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> ``` 在前述的代碼清單里,`title`屬性關聯于菜單項的顯示文本。因為我們用硬代碼設置這些屬性值,Andorid Studio將會標記警告。按F2在這些警告間跳躍并按`Alt+Enter`拉出智能建議。你只需簡單地按回車接受第一個建議,輸入新字符串資源的名稱,接著馬上彈出對話框,再按回車接受命名的資源。用`new_reminder`作為第一個條目的名稱,第二個叫`exit`。 打開`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 ```java @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; } } ``` 運行這個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作為提交信息。 ## 保持提醒 因為Reminders這個app需要保存提醒清單,你將需要一個保存策略。Android SDK和運行時系統提供了一個內建的數據庫引擎叫SQLite,它設計為有限記憶體環境并很適合于移動設備。這節涵括了SQLite數據庫并瀏覽怎么保存提醒清單。我們的策略將包括一個數據模型,一個數據庫代理類,還有一個游標適配器(`CursorAdapter`)。這個模型將維持數據讀寫到數據庫。代理將是一個適配器類將把從app簡單調用轉換為到數據庫API調用。最后,游標適配器將擴展為一個標準的Android類用于以抽象方式處理數據訪問。 ## 數據模型 讓我們開始創建數據模型。右擊`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 ```java 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; } } ``` 現在你將創建一個數據代理。再次,這個代理將轉換簡單的應用調用為低級別的SQLite API調用。在`com.apress.gerber.reminders`包里新建一個類叫`RemindersDbAdapter`。把清單5-9的代碼直接加入到這個新類里。當你解析導入時,發現D`atabaseHelper`并沒在Android SDK里。我們將在后面的步驟里定義`DatabaseHelper`。這些代碼定義了列名稱和索引;一個TAG作日志;兩個上下文對外對象;和一個SQL語句用于創建數據庫。 Listing 5-9. Code to be placed inside the `RemindersDbAdapter` class ```java //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是一個SQLite API類,用于打開和關閉數據庫。它用到了上下文`Context`,這是一個抽象的Android類以提供到Android操作系統的訪問。`DatabaseHelper`是一個用戶自定義類,且必須由你來定義。用清單5-10實施`DatabaseHelper`類,作為`RemindersDbAdapter`的內部類。把這些代碼放到`RemindersDbAdapter`后段,但在類結束的花括號的前面。 Listing 5-10. `RemindersDbAdapter` ```java 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 `繼承于`QLiteOpenHelper`,用于以特殊的回調方法來維護數據庫。回調方法是運行時環境在應用的整個生命周期內都調用的方法,并且它們用到`SQLiteDatabase db`變量提供SQL命令的執行。在構造器里數據庫就被初始化了。構造器傳遞數據庫名和版本到它的父類;然后父類做數據庫的設置繁雜工作。當需要建立數據庫時`onCreate()`方法被運行時自動調用。這個操作只運行一次,當app首次啟動并且數據庫還未創建時。`onUpgrade()`方法是在數據庫更新時被調用,例如假如開發者改變綱要。如果你改變數據庫的綱要,確保給`DATABASE_VERSION`增加1,然后`onUpgrade()`會處理剩下的事情。如果你忘了給`DATABASE_VERSION`加1,你的app將崩潰即便在調試構建模式下。在前述的代碼里,在運行`onCreate()`方法之前我們運行一個SQL命令來移除數據庫里唯一的表單,以方便重建表單。 清單5-11演示了用`DatabaseHelper`來打開和關閉數據庫。構造器保存了上下文的一個實例,它會被傳送到`DatabaseHelper`。`open(`)方法初始化helper并用它得到一個數據庫的實例,直到`close()`方法用于關閉數據庫。把這些代碼加入到`RemindersDbAdapter`類里,在所有成員變量之后和`DatabaseHelper`內部類之前。當你解析導入時,用`android.database.SQLException`類。 Listing 5-11. Database Open and Close Methods ```java 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(); } } ``` 清單5-12包含了所有處理在tbl_remdrs表單里創建,讀取,更新,和刪除`Reminder`對象的操作。通常參考CRUD操作;CRUD即代表創建,讀取,更新,刪除。加入這些代碼到`RemindersDbAdapter`類的`close()`方法之后。 Listing 5-12. Database CRUD Operations ```java //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); } ``` 每個方法都用到了`SQLiteDatabase mDb`變量來生成和執行SQL語句。如果你熟悉SQL,你會猜到這些SQL語句將由`INSERT`, `SELECT`, `UPDATE`, 或 `DELETE`組成。 兩個創建方法用到了特別的`ContentValues`對象,這個是數據載體用于在`insert`方法里傳送數據值到數據庫對象。在`insert`語句里數據庫最終將轉換這些對象到數據庫。有兩個讀方法,一個用于引出單個提醒另一個則引出一個游標以遍歷所有的提醒。晚點在一個特別的`Adapter`類里你將用到游標。 更新方法象第二個創建方法。無論怎樣,這個方法調用了底層的數據庫對象的更新方法,那個將生成并執行一個更新SQL語句而不是一個插入語句。 最后,有兩個刪除方法。第一個針對特定的提醒用 `id`參數和數據庫對象來生成和執行一條刪除語句。第二個方法需要數據庫生成并執行一條刪除語句來移除所有表單里的提醒。 最后,有兩個刪除方法。第一個針對特定的提醒用 `id`參數和數據庫對象來生成和執行一條刪除語句。第二個方法需要數據庫生成并執行一條刪除語句來移除所有表單里的提醒。 這時,你需要一個手段從數據庫提出提醒并放入到`ListView`。清單5-13演示了必要的邏輯,通過繼承之前你看到的特別的`Adapter` Android類來綁定數據庫值到單獨的行對象。創建一個新類`RemindersSimpleCursorAdapter`在`com.apress.gerber.reminders`包下,并完成處理代碼。當解析導入類時,使用`android.support.v4.widget.SimpleCursorAdapter`類。 Listing 5-13. R`emindersSimpleCursorAdapter` Code ```java public class RemindersSimpleCursorAdapter extends SimpleCursorAdapter { public RemindersSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); } //to use a viewholder, you must override the following two methods and define a ViewHolder class @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return super.newView(context, cursor, parent); } @Override public void bindView(View view, Context context, Cursor cursor) { super.bindView(view, context, cursor); ViewHolder holder = (ViewHolder) view.getTag(); if (holder == null) { holder = new ViewHolder(); holder.colImp = cursor.getColumnIndexOrThrow(RemindersDbAdapter.COL_IMPORTANT); holder.listTab = view.findViewById(R.id.row_tab); view.setTag(holder); } if (cursor.getInt(holder.colImp) > 0) { holder.listTab.setBackgroundColor(context.getResources().getColor(R.color.orange)); } else { holder.listTab.setBackgroundColor(context.getResources().getColor(R.color.green)); } } static class ViewHolder { //store the column index int colImp; //store the view View listTab; } } ``` 我們用適配器把所有提醒登記到`ListView`。在運行時中,`ListView`將重復調用在適配器里的`bindView()`方法,以單獨的示圖對象作為用戶裝載器,且在清單里滾動。填入這些清單條目到示圖里是適配器的工作。在這個例子代碼里,我們使用了適配器的子類`SimpleCursorAdapter`。這個類用了一個游標對象,它保存著跟蹤表單里的行軌跡。 這里你看到了一個`ViewHolder`模式的例子。這是一個容易認識的Android模式,每個`ViewHolder`對象含有一個示圖的標簽。用數據源(在這個例子里是`Cursor`)的值,這個對象加載清單里的示圖對象。`ViewHolder`定義為一個內部靜態類,有兩個實例變量,一個用于索引重要的表單項另一個用于在布局里定義的`row_tab`示圖。 `bindView()`方法開始于父類在示圖里從游標到元素的`map`值方法的調用。然后檢查看(holder)是否附有一個標簽還是有必要創建一個新的(holder)。然后`bindView()`方法用重要列索引和早先定義的`row_tab`配置容器的實例變量。在容器被發現或配置后,從當前提醒的`COL_IMPORTANT`常量秋決定`row_tab`用什么顏色。這個例子用了新的橙色,那個你要加到`colors.xml`: `<color name="orange">#ffff381a</color>`。 早先你用了`ArrayAdapter`來管理模型和示圖之間的關系。`SimpleCursorAdapter`也是用同樣的模式,雖然它的模型是SQLite數據庫。將清單5-14更改到你的`RemindersDbAdaper`和`RemindersSimpleCursorAdapter`類里。 Listing 5-14. `RemindersActivity` Code ```java public class RemindersActivity extends ActionBarActivity { private ListView mListView; private RemindersDbAdapter mDbAdapter; private RemindersSimpleCursorAdapter mCursorAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_reminders); mListView = (ListView) findViewById(R.id.reminders_list_view); mListView.setDivider(null); mDbAdapter = new RemindersDbAdapter(this); mDbAdapter.open(); Cursor cursor = mDbAdapter.fetchAllReminders(); //from columns defined in the db String[] from = new String[]{ RemindersDbAdapter.COL_CONTENT }; //to the ids of views in the layout int[] to = new int[]{ R.id.row_text }; mCursorAdapter = new RemindersSimpleCursorAdapter( //context RemindersActivity.this, //the layout of the row R.layout.reminders_row, //cursor cursor, //from columns defined in the db from, //to the ids of views in the layout to, //flag - not used 0); // the cursorAdapter (controller) is now updating the listView (view) //with data from the db (model) mListView.setAdapter(mCursorAdapter); } //Abbreviated for brevity } ``` 這時候如果你運行app,你還是看不到清單里有任何東西;屏幕完全是空的,因為你最后的修改在例子的數據部分插入了數據庫功能。按`Ctrl+K | Cmd+K`并提交的修改,提交信息:Adds SQLite database persistence for reminders and a new color for important reminders。聰明點的話,你可能想弄清楚怎么用新的`RemindersDbAdaper`把例子里的條目加回來。這將在下章描述,你可以繼續看下去并檢查下作業了。 ## 小結 致此,你有了個成熟的Android應用。在這章,你學會了怎樣設置第一個Android項目并用Git控制代碼。你也探索了怎么編輯Android布局,用設計或文本模式。你也看到建立一個在動作條里的溢出菜單。這章的最后探索了`ListView`和`Adapter`,以及綁定數據到內建的SQLite數據庫。在接下來的章節里,增加創建和編輯提醒的功能,你將完成這個app。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看