<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 第四章:重構代碼 > 譯者:[qiangxcn](http://ask.android-studio.org/?/people/qiangxcn) > 來源:[Learn Android Studio 漢化教程 第四章 : Refactoring Code](http://ask.android-studio.org/?/article/106) 在Android Studio中開發,解決方案不會總是一蹴而成的。作為一個有效率的編程者,在你的開發,調試和測試中需要一些彈性以及代碼重構。隨著在這章中的行進,你將明白Android Studio如何產生代碼;在這章里你將看到Android Studio如何重構你的代碼。重構代碼最大的風險是可能引入不期望的錯誤。通過分析某些風險重構操作的結果,Android Studio減低了這些風險,然后激活Find tool窗口,在發行前,你可以預覽你的更改-那里標志著任何錯誤或沖突。 在這章里描述的許多重構操作也可不用Android Studio的重構工具來執行。無論怎樣,你必須避免強行重構(例如:通過一個全文的查找/替換操作來重組代碼),因為在這些情形下Android Studio不能從引入的錯誤中一直保護你。相反,如果Android Studio發現你企圖一個重構操作,它將盡力避免你犯任何愚蠢錯誤。例如,在Project tool窗口中拖動一個JAVA源文件從一個包到另一個包,這將強制產`Refactor ? Move`操作,由此會分析你的移動操作結果,允許你預覽那些改變,然后適當地改變類中所有的`import`語句以適應合格的新全包名。 絕大多數的重構操作被限制于一個方法或一個類里面,因而將不太會引入錯誤到你的項目中。危險的重構操作是那些涉及到兩個或以上的資源文件。如果重構操作引入編譯錯誤,檢查管理器將在編輯器里用紅標簽標志那些被影響的資源文件。基于這點,你或者可以企圖去修正它們,或者用`Ctrl+Z|Cmd+Z`簡單地取消這個重構操作了。如果重構操作以沒有編譯錯誤完成,然而涉及到太多資源文件,那你還是必須要測試及校驗你是否引入了任何實時錯誤。第11章涵蓋了測試。 提示:你必須提交任何重要的重構更改,作為單一的Git提交,因此之后你可以輕松地回復那個提交。第7章涵蓋了Git。 這章聚焦于用最好的工具來執行重構操作。在我們探訪獨立的重構操作之前,我們樂于指出Android Studio有一個極其便利的重構工具叫`Refactor ?Refactor This`.總在上下文菜單中選擇這個,圖4-1所示,集成了絕大多數有用的重構操作。快捷鍵是`Ctrl+Alt+Shift+T | Ctrl+T`,在PC上你可以方便地記首字母CAST。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c142539.png) 圖4-1:重構器Refactor This菜單,包括了大部分的有用重構操作。 在你開始本章的例子之前,修改第3章的`Sandbox.java`文件,它沒擴充和包含任何方法或成員變量,象下面的小片段: ```java public class Sandbox { } ``` ## 重命名 在Project tool窗口中選擇Sandbox并導航到`Refactor? Rename`或按`Shift+F6`.引出一個對話框以允許你重命名你的類,另外也可以重命名出現在注釋中,測試實例,以及繼承類中的那些名字。重命名`Sandbox`為`Playpen`并點擊Refactor按鈕,如圖4-2所示。你將看到在你項目中重命名的操作。現在請用`Ctrl+Z | Cmd+Z`取消這個操作。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c15f126.png) 圖4-2:重命名Sandox為Playpen ## 修改簽名 更改簽名的操作允許你改變方法的下列屬性:可視性,名稱,返回類型,參數,以及例外拋出。在`Sandbox.java`里創建一個方法,如下面的代碼片斷: ```java public String greetings(String message){ return "Hello " + message; } ``` 將光標移到單詞`greetings`上面(高亮的粗體字)并按`Ctrl+F6 |Cmd+F6`,或導航到`Refactor ? Change Signature`。結果對話框會允許你修改方法的簽名,如圖4-3所示。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c184748.png) 圖4-3:修改簽名對話框 在參數表里,點擊字符串類型參數`message`這項,將它的名稱從`message`改為`greet`,如圖4-3所示。圖標綠色的`+`和紅色的`-`允許你分別增加或減少方法的參數。并且,你也可以編輯參數表里面它們的類型和名稱。另外,修改當前方法時,你可能決定選擇委托重載方法的單選按鈕。選擇這個按鈕將保留你的原始方法不受影響,但會生成另一個你新定義簽名的方法。在JAVA里如果你可能考慮一系列有相同的名稱重載方法,但參數的順序和/或參數的類型不同。無論如何,你做的更改并沒限制方法的重載。如果你希望的話通過點擊預覽按鈕,可以在提交它們之前預覽。按Refactor按鈕完成并離開。 ## 類型移植 如標題所述,類型移植允許你從一個JAVA類型移植到另一個。讓我們假設你創建了一個`Person`類。隨著你的開發進行,你發現`Person`太一般了,因而你又創建了一個`Manager`類擴展于`Person`。如果你想移植所有的`Person`實例到`Manager`,你可以用類型移植輕松辦到。 將光標放到`greetings`方法的`String`聲明上(在下面代碼片段中的高亮粗體字)并且按`Ctrl+Shift+F6 | Cmd+Shift+F6`或選擇`Refactor ? Type Migration`。結果對話框如圖4-4所示。 ```java public String greetings(String greet){ return "Hello " + greet; } ``` ![](https://box.kancloud.cn/2016-08-06_57a5d3c1a0d81.png) 圖4-4:類型移植,從`String`到`date` 更改`java.lang.String`到`java.util.Date`,如圖4-4所示。從選擇范圍框的下拉菜單里選擇打開文件。如同大多數重構操作,通過點擊預覽按鈕,你可預覽你的更改。這里我們按Refactor按鈕。 移動 你可以通以下三種方法中的一個方法來移動源代碼文件。 + 在Project tool窗口拖動源文件從一個包到另一個包中; + 選擇源文件從主菜單導航到`Refactor ? Move`; + 在Project tool窗口選擇源文件并按下`F6`。 右鍵點擊(在Mac電腦上`Ctrl`-click)`com.apress.gerber.helloworld`包并選擇`New ? Package`。給這個重構目標包命名。從Project tool窗口,把`sandbox.java`拖放到重構目標包里,當出現圖4-5對話框時按OK。在Project tool窗口中執行的任何拖放操作將自動產生一個重構移動操作,這個會讓你安全地把一個類從一個包移動到別一個包里。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c1ba5a1.png) 圖4-5:由于拖放操作導致的重構移動對話框 除了移動類之外,你也可以移動成員變量。在你的`Sandbox.class`中,定義一個新成員變量如下: ```java public static final String HELLO = "Hello Android Studio"; ``` 移動光標到這行代碼上并按下F6。導致一個對話框允許你移動成員變量從一個類到另一個。如圖4-6所示。請點擊取消按鈕來取消這次操作。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c1d0e91.png) 圖4-6:移動成員變量的對話框 ## 復制 復制,有點象移動,按快捷鍵`F5`或選擇主菜單里的`Refactor ? Copy`來訪問。在Project tool窗口,選擇之前重構的包中的`Sandbox.java`并按下`F5`鍵。在目標包的拖放菜單中選擇`com.apress.gerber.helloworld`包并點擊OK,如圖4-7所示。象我們這里無差別地復制JAVA源文件不是一個好主意,因為結果不明確且普通存在著錯誤。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c1ec961.png) 圖4-7:復制類的對話框 ## 安全刪除 讓我們來刪除剛才復制的類。在Android Studio的Project tool窗口里用Delete按鍵,你總可以刪除文件和資源。在剛才重構包中點擊`Sandbox.java`文件并按下Delete鍵。結果對話框允許你使用安全刪檢查選項來刪除。安全刪除的先進之處在于執行刪除前我們可查詢任何因依賴于這個資產而可能導致的破壞,如圖4-8所示。如果在這個項目中發任何東西依賴于這個資產,將給出一個可選項瀏覽它們,或點擊無論如何都刪除可選項來強制刪除。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c2135ce.png) 圖4-8:安全刪除對話框 ## 析出 析出不是一個操作而是幾個。這節涵括了一些重要的析出操作:析出變量,析出常量,析出域,析出參數,和析出方法。在·Sandbox.class·里,讓我們先移走所有的成員變量和方法從白紙開始: ```java public class Sandbox { } ``` ## 析出變量 在你的`Sandbox.java`類里,定義一個方法如下示: ```java private String saySomething(){ return "Something"; } ``` 把光標放到硬編碼Something的值(粗體字)上并選擇`Refactor ? Extract ? Variable`,或者按`Ctrl+Alt+V | Cmd+Alt+V`接著按回車,不要選擇聲明`final`的復選框。Android Studio依據硬編碼字符串析出一個本地變量并命名它。你將以如下代碼告終: ```java private String saySomething(){ String something = "Something"; return something; } ``` ## 析出常量 當你開發Android的APP時,會發現你會用很多的字符串作為鍵-例如,在`Map`和`Bundle`里。因此,析出常量將會節省你大量的時間。 定義一個方法象如下的代碼片段。把光標放到`name_key`字符串上并按`Ctrl+Alt+C | Cmd+Alt+C`。結果對話框將如圖4-9所示。這里,Android Studio提供一些建議的名稱。按慣例,常量在JAVA里都應該是大寫的。選擇`NAME_KEY`并按回車。 注意:為了創建和處理這個方法而不發生編譯錯誤,你必須導入`android.os.Bundle` ```java private void addName(String name, Bundle bundle ){ bundle.putString("name_key", name); } ``` 結束時你將看一個常量名稱是`NAME_KEY`,象以下定義的: ```java public static final String NAME_KEY = "name_key"; ``` ![](https://box.kancloud.cn/2016-08-06_57a5d3c22bc23.png) 圖4-9:析出常量NAME_KEY ## 析出域 析出域將轉換一個本地變量到你的類域(a.k.a.成員變量)里。 注意:為了創建和處理這個方法而不發生編譯錯誤,你必須導入`android.os.Bundle` 在你的`Sandbox`類里定義一個方法: ```java private Date getDate(){ return new Date(); } ``` 把光標放到`Date`(粗體高亮)上并按鍵`Ctrl+Alt+F | Cmd+Alt+F`。你將看到一個對話框如圖4-10所示。在Android里,按慣例域(a.k.a. 成員變量)名的頭字母用`m`。你將會注意到一個下拉菜單允許你初始化當前方法中的域,域聲明,或構造器。選擇域聲明并按回車。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c244b38.png) 圖4-10:析出域對話框 結果如下: ```java private final Date mDate = new Date(); ... private Date getDate(){ return mDate; } ``` 移除`final`關鍵字,結果這個域聲明如下: ```java private Date mDate = new Date(); ``` ## 析出參數 析出參數允許你析出一個變量并放到封套的方法里。在你的`Sandbox`類里定義一個方法: ```java private void setDate(){ mDate = new Date(); } ``` 將光標放到Date()(粗體高亮)上,`按Ctrl+Alt+P | Cmd+Alt+P`接著按回車。結果這個方法如下代碼片段所示: ```java private void setDate(Date date){ mDate = date; } ``` ## 析出方法 析出方法讓你選擇一行或多行行連續的代碼放到一個分離的方法中。有兩個原因你會想做這個。首先是方法太復雜了。相對于100行的代碼,打斷它到約10到20行的算法塊會比較容易閱讀且會較少錯誤。 再者,重復的代碼從來就不是好主意,因而如果你發現了重復的代碼,最好析出它們成一個方法并在重復的地方調用它。通過析出之前重復的代碼到一個方法里并調用它,你可以保留你的方法在一個地方,如果你想修改它,你只要修改一次。在你的`Sandbox`類里重建下面的兩個方法如清單4-1。你可以自由地復制和粘貼。 清單4-1 ```java private String methodHello (){ String greet = "Hello"; StringBuilder stringBuilder = new StringBuilder(); for(int nC = 0; nC < 10; nC++){ stringBuilder.append(greet + nC); } return stringBuilder.toString(); } private String methodGoodbye (){ String greet = "Goodbye"; StringBuilder stringBuilder = new StringBuilder(); for(int nC = 0; nC < 10; nC++){ stringBuilder.append(greet + nC); } return stringBuilder.toString(); } ``` 象我們已經提到過的,任何時候你發現重復一個代碼塊或復制和粘貼代碼塊,你就必須考慮析出方法了。選擇清單4-1中粗體高亮的塊。現在按`Ctrl+Alt+M | Cmd+Alt+M`析出方法。將呈現一個對話框列出方法的簽名。重命名這個方法為`getGreet`,如圖4-11所示,接著點擊OK。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c26017a.png) 圖4-11:析出方法對話框 Android Studio掃描你的文件并看到你有另外一個確鑿的代碼塊案例。在處理復制對話框里點擊Yes接受建議,如圖4-12所示。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c27f82b.png) 圖4-12:復制處理對話框 你將看到清單4-2的代碼。現在結果方法很容易保留在某個地方。 清單 4-2.從析出方法操作里得出的結果代碼 ```java private String methodHello (){ String greet = "Hello"; return getGreet(greet); } private String methodGoodbye (){ String greet = "Goodbye"; return getGreet(greet); } private String getGreet (String greet){ StringBuilder stringBuilder = new StringBuilder(); for(int nC = 0; nC < 10; nC++){ stringBuilder.append(greet + nC); } return stringBuilder.toString(); } ``` ## 高級重構 整個這章所描述的剩下的其他重構操作是高級別的。如果你有興趣簡單迅速地提高Android Studio,已經有了足夠的知識來有效地使用重構操作,也許你可以跳過這節。但無論如何,如果你對JAVA有比較好的理解并且想鉆研更多的重構操作,繼續看下去吧。 移除Sandbox.java里的所有成員變量及方法,從一張白紙開始。 ```java public class Sandbox { } ``` 右鍵點擊(Mac電腦用`Ctrl`+點擊)Project tool窗口里的`com.apress.gerber.helloworld`包,選擇`New ? Java Class`。命名這個類為`Minibox`。修改Minibox類定義繼承自`Sandbox`并且有個成員變量叫做`mShovel`,如這里所示: ```java public class Minibox extends Sandbox { private String mShovel; } ``` ## 推高成員變量以及拉低成員變量 推高成員變量以及拉低成員變量用于繼承。注意到我們定義了一個`mShovel`成員變量在`Minibox`類里。讓我們假設`mShovel`可能對于其他繼承自`Sandbox`類的子類也有用。這樣做,打開`Minibox`類并選擇`Refactor ? Pull Members Up`。結果對話框如圖4-13所示。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c296a9d.png) 圖 4-13: 推高成員變量對話框 `mShove`l會被缺省地選中,并且因為`Sandbox`是`Minibox`的父類所以推高成員變量組合窗口會缺省地設定在`com.apress.gerber.helloworld.Sandbox`類上。點擊Refactor,檢視`Sandbox`和`Minibox`,你將發現`mShovel`成員變量不再出現在`Minibox`里了,而屬于`Sandbox`。作為一般規則,如果你覺得一個成員變量對其他擴展類也是有用的,那么就把這些成員變量在繼承層次里推高。用類似的手法可以拉低成員變量。 ## 解除繼承并委托成員變量 右鍵點擊(Mac電腦用`Ctrl`+點擊)`com.apress.gerber.helloword`包選擇`New ? Java Class`。命名這個新類為`Patio`并繼承自`Sandbox`: ```java public class Patio extends Sandbox { } ``` 進一步分析后,我們決定`Patio`不是一個`Sandbox`,但更象是它擁有一個`Sandbox`。為了改變它們的關系,導航到`Refactor ? Replace Inheritance with Delegation`。在結果對話框里,點擊為委托成產生`getter`方法,如圖4-14所示。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c2b3d65.png) 圖 4-14:解除繼承并委托成員變量對話框 現在你的`Patio`類將擁有一個`Sandbox`成員變量,如下代碼片段所示: ```java public class Patio { private final Sandbox mSandbox = new Sandbox(); public Sandbox getSandbox() { return mSandbox; } } ``` 封裝域 封裝域是一種面向對象策略,通過使訪問級別為私有來隱藏類成員變量并提供以公開的`getter/setter`方法作為公開的接口。盡管當你選擇`Refactor ? Encapsulate Fields`時有很多的選擇,但`Refactor ? Encapsulate Fields`類似于`Code ? Generate ? Getter and Setter`。打開你的`Sandbox`類并定義一個成員變量叫`mChildren`,如下面代碼片段中的粗體高亮部分。從主菜單,選擇`Refactor ? Encapsulate Fields`。 ```java public class Sandbox { private String mShovel; private int mChildren; } ``` 結果對話框允許你精確地選擇怎樣封裝這些域以及它們的訪問級別。真正地封裝域將有一個私有的可視度及公有的訪問(`getter`)及改變(`setter`)方法。點擊Refactor按鈕,如圖4-15所示,注意到Android Studio在我們的`Sandbox.java`類里為我們生成所有的`getter`和`setter`。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c2d1398.png) 圖 4-15:封裝域對話框 ## 包裝方法的返回值類型 當你需要返回一個對象而不是基本數據類型時,包裝返回值可能是有用的(當然還有其他的情形你可能想包裝一個返回值)。把光標放到`getChildren()`方法上并導航到`Refactor ? Wrap Method Return Value`。選擇Use Existing Class選項,名稱框輸入`java.lang.Integer`,包裝域框則選擇value,如圖4-16所示。現在點擊Refactor按鈕且注意到你的`getChildren()`方法返回一個`Integer`類,而不是基本數據類型`int`。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c30222e.png) 圖 4-16: 包裝返回值對話框 ## 用工廠方法代替構造器 把光標放在`Sandbox`類定義附欄內。按`Alt+Insert | Cmd+N`接著選擇生成一個新構造器。選擇所有成員變量,如圖4-17所示,然后點擊OK。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c31eb76.png) 圖 4-17:通過構造器來選擇域的對話框 將光標放到如下所示代碼片段構造器的任何位置,并導航到`Refactor ? Replace Constructor with Factory Method`。結果對話框象圖4-18所示。點擊Refactor來生成一個工廠方法。 ```java public Sandbox(String shovel, int children) { mShovel = shovel; mChildren = children; } ``` ![](https://box.kancloud.cn/2016-08-06_57a5d3c33f7e2.png) 圖 4-18: 用工廠模式代替構造器的對話框 注意到之前的構造器現在變成`private`了并且一個新的靜態方法返回`Sandbox`類的實例,如下面代碼片段所示。如果你正創建一個單例類,這將會是非常有用的。 ```java public static Sandbox createSandbox(String shovel, int children) { return new Sandbox(shovel, children); } ``` ## 轉換匿名內部類 在你的Sandbox類的構造器里加上下面行: ```java new Thread(new Runnable()).start(); ``` 把光標放在`Runnable()`上并按下`Alt+Enter`來調用完成代碼操作。然后選擇實現方法。選擇`run()`方法并點擊OK。你的代碼將象下面片段所示: ```java new Thread(new Runnable() { @Override public void run() { //do something } }).start(); ``` 把光標放在`Runnable()`上并導航到`Refactor ? Convert Anonymous to Inner`。Android Studio建議`MyRunnable`作為這個類名,如圖4-19所示。去選Make class static選項后點擊OK。注意到你將在`Sandbox`類里得到一個私有的內部類叫`MyRunnable`,它實現`Runnable`接口。這個例子沒有做更多的事;不管怎樣,當委派`View`的行為時你也許有機會用到這個。 ![](https://box.kancloud.cn/2016-08-06_57a5d3c36185d.png) 圖 4-19: 轉換匿名內部類的對話框 ## 小結 這章討論了Android Studio目前有效的許多重構操作。重構代碼是編程工程的一個必需的部分,Android Studio里的重構工具是最好的重構工具之一。Android Studio通過分析推理以及允許你于提交操作前在Find tool窗口預覽結果,減低了某些操作執行的風險。最重要的是重構操作`Refactor ? Refactor This`對話框是如此有效的,這個可以通過用快捷鍵`Ctrl+Alt+Shift+T | Ctrl+T`來調用。
                  <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>

                              哎呀哎呀视频在线观看