[Learn Android Studio 漢化教程]第四章 : Refactoring Code

來源:互聯網
上載者:User

標籤:

[Learn Android Studio 漢化教程]第四章 : Refactoring Code

 

第四章Refactoring Code    重構代碼

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


圖4-1:重構器Refactor This菜單,包括了大部分的有用重構作業。

在你開始本章的例子之前,修改第3章的Sandbox.java檔案,它沒擴充和包含任何方法或成員變數,象下面的小片段:
public class Sandbox {
}

Rename  重新命名

在Project tool視窗中選擇Sandbox並導航到Refactor? Rename或按Shift+F6.引出一個對話方塊以允許你重新命名你的類,另外也可以重新命名出現在注釋中,測試執行個體,以及繼承類中的那些名字。重新命名Sandbox為Playpen並點擊Refactor按鈕,4-2所示。你將看到在你項目中重新命名的操作。現在請用Ctrl+Z | Cmd+Z取消這個操作。


圖4-2:重新命名Sandox為Playpen

Change Signature   修改簽名

更改簽名的操作允許你改變方法的下列屬性:可視性,名稱,傳回型別,參數,以及例外拋出。在Sandbox.java裡建立一個方法,如下面的代碼片斷:
public String greetings(String message){
return "Hello " + message;
}

將游標移到單詞greetings上面(高亮的粗體字)並按Ctrl+F6 |Cmd+F6,或導航到Refactor ? Change Signature。結果對話方塊會允許你修改方法的簽名,4-3所示。


圖4-3:修改簽名對話方塊
    在參數表裡,點擊字串型別參數message這項,將它的名稱從message改為greet,4-3所示。表徵圖綠色的+和紅色的-允許你分別增加或減少方法的參數。並且,你也可以編輯參數表裡面它們的類型和名稱。另外,修改當前方法時,你可能決定選擇委託重載方法的選項按鈕。選擇這個按鈕將保留你的原始方法不受影響,但會產生另一個你新定義簽名的方法。在JAVA裡如果你可能考慮一系列有相同的名稱重載方法,但參數的順序和/或參數的類型不同。無論如何,你做的更改並沒限制方法的重載。如果你希望的話通過點擊預覽按鈕,可以在提交它們之前預覽。按Refactor按鈕完成並離開。

Type Migration  類型移植

如標題所述,類型移植允許你從一個JAVA類型移植到另一個。讓我們假設你建立了一個Person類。隨著你的開發進行,你發現Person太一般了,因而你又建立了一個Manager類擴充於Person。如果你想移植所有的Person執行個體到Manager,你可以用類型移植輕鬆辦到。

將游標放到greetings方法的String聲明上(在下面程式碼片段中的高亮粗體字)並且按Ctrl+Shift+F6 | Cmd+Shift+F6或選擇Refactor ? Type Migration。結果對話方塊4-4所示。
public String greetings(String greet){
return "Hello " + greet;
}


圖4-4:類型移植,從String到date

更改java.lang.String到java.util.Date,4-4所示。從選擇範圍框的下拉式功能表裡選擇開啟檔案。如同大多數重構作業,通過點擊預覽按鈕,你可預覽你的更改。這裡我們按Refactor按鈕。

Move   移動

你可以通以下三種方法中的一個方法來移動原始碼檔案。
? 在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視窗中執行的任何拖放操作將自動產生一個重構移動操作,這個會讓你安全地把一個類從一個包移動到別一個包裡。


圖4-5:由於拖放操作導致的重構移動對話方塊

除了移動類之外,你也可以移動成員變數。在你的Sandbox.class中,定義一個新成員變數如下:
public static final String HELLO = "Hello Android Studio";

移動游標到這行代碼上並按下F6。導致一個對話方塊允許你移動成員變數從一個類到另一個。4-6所示。請點擊取消按鈕來取消這次操作。


圖4-6:移動成員變數的對話方塊

Copy   複製

複製,有點象移動,按快速鍵F5或選擇主菜單裡的Refactor ? Copy來訪問。在Project tool視窗,選擇之前重構的包中的Sandbox.java並按下F5鍵。在目標包的拖放菜單中選擇com.apress.gerber.helloworld包並點擊OK,4-7所示。象我們這裡無差別地複製JAVA源檔案不是一個好主意,因為結果不明確且普通存在著錯誤。


圖4-7:複製類的對話方塊

Safe Delete   安全刪除

讓我們來刪除剛才複製的類。在Android Studio的Project tool視窗裡用Delete按鍵,你總可以刪除檔案和資源。在剛才重構包中點擊Sandbox.java檔案並按下Delete鍵。結果對話方塊允許你使用安全刪檢查選項來刪除。安全刪除的先進之處在於執行刪除前我們可查詢任何因依賴於這個資產而可能導致的破壞,4-8所示。如果在這個項目中發任何東西依賴於這個資產,將給出一個可選項瀏覽它們,或點擊無論如何都刪除可選項來強制移除。


圖4-8:安全刪除對話方塊

Extract 析出

析出不是一個操作而是幾個。這節涵括了一些重要的析出操作:析出變數,析出常量,析出域,析出參數,和析出方法。在Sandbox.class裡,讓我們先移走所有的成員變數和方法從白紙開始:
public class Sandbox {
}

Extract Variable 析出變數

在你的Sandbox.java類裡,定義一個方法如下示:
private String saySomething(){
return "Something";
}

把游標放到寫入程式碼Something的值(粗體字)上並選擇 Refactor ? Extract ? Variable,或者按Ctrl+Alt+V | Cmd+Alt+V接著按斷行符號,不要選擇聲明final的複選框。Android Studio依據寫入程式碼字串析出一個本地變數並命名它。你將以如下代碼告終:
private String saySomething(){
String something = "Something";
return something;
}

Extract Constant 析出常量

當你開發Android的APP時,會發現你會用很多的字串作為鍵-例如,在Map和Bundle裡。因此,析出常量將會節省你大量的時間。

定義一個方法象如下的程式碼片段。把游標放到name_key字串上並按Ctrl+Alt+C | Cmd+Alt+C。結果對話方塊將4-9所示。這裡,Android Studio提供一些建議的名稱。按慣例,常量在JAVA裡都應該是大寫的。選擇NAME_KEY並按斷行符號。
注意:為了建立和處理這個方法而不發生編譯錯誤,你必須匯入android.os. Bundle
private void addName(String name, Bundle bundle ){
bundle.putString("name_key", name);
}

結束時你將看一個常量名稱是NAME_KEY,象以下定義的:
public static final String NAME_KEY = "name_key";


圖4-9:析出常量NAME_KEY

Extract Field  析出域

析出域將轉換一個本地變數到你的類域(a.k.a.成員變數)裡。
注意:為了建立和處理這個方法而不發生編譯錯誤,你必須匯入android.os. Bundle
在你的Sandbox類裡定義一個方法:
private Date getDate(){
return new Date();
}

把游標放到Date(粗體高亮)上並按鍵Ctrl+Alt+F | Cmd+Alt+F。你將看到一個對話方塊4-10所示。在Android裡,按慣例域(a.k.a. 成員變數)名的頭字母用m。你將會注意到一個下拉式功能表允許你初始化當前方法中的域,域聲明,或構造器。選擇域聲明並按斷行符號。


圖4-10:析出域對話方塊

結果如下:
private final Date mDate = new Date();
...
private Date getDate(){
return mDate;
}
移除final關鍵字,結果這個域聲明如下:
private Date mDate = new Date();

Extract Parameter  析出參數

析出參數允許你析出一個變數並放到封套的方法裡。在你的Sandbox類裡定義一個方法:
private void setDate(){
mDate = new Date();
}

將游標放到Date()(粗體高亮)上,按Ctrl+Alt+P | Cmd+Alt+P接著按斷行符號。結果這個方法如下程式碼片段所示:
private void setDate(Date date){
mDate = date;
}

Extract Method  析出方法

析出方法讓你選擇一行或多行行連續的代碼放到一個分離的方法中。有兩個原因你會想做這個。首先是方法太複雜了。相對於100行的代碼,打斷它到約10到20行的演算法塊會比較容易閱讀且會較少錯誤。

再者,重複的代碼從來就不是好主意,因而如果你發現了重複的代碼,最好析出它們成一個方法並在重複的地方調用它。通過析出之前重複的代碼到一個方法裡並調用它,你可以保留你的方法在一個地方,如果你想修改它,你只要修改一次。在你的Sandbox類裡重建下面的兩個方法如清單4-1。你可以自由地複製和粘貼。
清單4-1
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。


圖4-11:析出方法對話方塊

Android Studio掃描你的檔案並看到你有另外一個確鑿的代碼塊案例。在處理複製對話方塊裡點擊Yes接受建議,4-12所示。


圖4-12:複製處理對話方塊

你將看到清單4-2的代碼。現在結果方法很容易保留在某個地方。
清單 4-2.從析出方法操作裡得出的結果代碼
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();
}

Advanced Refactoring   進階重構

整個這章所描述的剩下的其他重構作業是進階別的。如果你有興趣簡單迅速地提高Android Studio,已經有了足夠的知識來有效地使用重構作業,也許你可以跳過這節。但無論如何,如果你對JAVA有比較好的理解並且想鑽研更多的重構作業,繼續看下去吧。

移除Sandbox.java裡的所有成員變數及方法,從一張白紙開始。
public class Sandbox {
}
右鍵點擊(Mac電腦用Ctrl+點擊)Project tool視窗裡的com.apress.gerber.helloworld包,選擇New ? Java Class。命名這個類為Minibox。修改Minibox類定義繼承自Sandbox並且有個成員變數叫做mShovel,如這裡所示:
public class Minibox extends Sandbox {
private String mShovel;
}

Push Members Down and Pull Members Up   推高成員變數以及拉低成員變數

推高成員變數以及拉低成員變數用於繼承。注意到我們定義了一個mShovel成員變數在Minibox類裡。讓我們假設mShovel可能對於其他繼承自Sandbox類的子類也有用。這樣做,開啟Minibox類並選擇Refactor ? Pull Members Up。結果對話方塊4-13所示。


圖 4-13: 推高成員變數對話方塊

mShovel會被預設地選中,並且因為Sandbox是Minibox的父類所以推高成員變數組合視窗會預設地設定在com.apress.gerber.helloworld.Sandbox類上。點擊Refactor,檢視Sandbox和Minibox,你將發現mShovel成員變數不再出現在Minibox裡了,而屬於Sandbox。作為一般規則,如果你覺得一個成員變數對其他擴充類也是有用的,那麼就把這些成員變數在繼承層次裡推高。用類似的手法可以拉低成員變數。

Replace Inheritance with Delegation   解除繼承並委託成員變數

右鍵點擊(Mac電腦用Ctrl+點擊)com.apress.gerber.helloword包選擇New ? Java Class。命名這個新類為Patio並繼承自Sandbox:
public class Patio extends Sandbox {
}

進一步分析後,我們決定Patio不是一個Sandbox,但更象是它擁有一個Sandbox。為了改變它們的關係,導航到Refactor ? Replace Inheritance with Delegation。在結果對話方塊裡,點擊為委託成產生getter方法,4-14所示。


圖 4-14:解除繼承並委託成員變數對話方塊

現在你的Patio類將擁有一個Sandbox成員變數,如下程式碼片段所示:
public class Patio {
private final Sandbox mSandbox = new Sandbox();
public Sandbox getSandbox() {
return mSandbox;
}
}

Encapsulate Fields   封裝域

封裝域是一種物件導向策略,通過使存取層級為私人來隱藏類成員變數並提供以公開的getter/setter方法作為公開的介面。儘管當你選擇Refactor ? Encapsulate Fields時有很多的選擇,但Refactor ? Encapsulate Fields類似於Code ? Generate ? Getter and Setter。開啟你的Sandbox類並定義一個成員變數叫mChildren,如下面程式碼片段中的粗體高亮部分。從主菜單,選擇Refactor ? Encapsulate Fields。
public class Sandbox {
private String mShovel;
private int mChildren;
}

結果對話方塊允許你精確地選擇怎樣封裝這些域以及它們的存取層級。真正地封裝域將有一個私人的可視度及公有的訪問(getter)及改變(setter)方法。點擊Refactor按鈕,4-15所示,注意到Android Studio在我們的Sandbox.java類裡為我們產生所有的getter和setter。


圖 4-15:封裝域對話方塊

Wrap Method Return Value   封裝方法的傳回值類型

當你需要返回一個對象而不是基礎資料型別 (Elementary Data Type)時,封裝傳回值可能是有用的(當然還有其他的情形你可能想封裝一個傳回值)。把游標放到getChildren()方法上並導航到Refactor ? Wrap Method Return Value。選擇Use Existing Class選項,名稱框輸入java.lang.Integer,封裝域框則選擇value,4-16所示。現在點擊Refactor按鈕且注意到你的getChildren()方法返回一個Integer類,而不是基礎資料型別 (Elementary Data Type)int。


圖 4-16: 封裝傳回值對話方塊

Replace Constructor with Factory Method   用Factory 方法代替構造器

把游標放在Sandbox類定義附欄內。按Alt+Insert | Cmd+N接著選擇產生一個新構造器。選擇所有成員變數,4-17所示,然後點擊OK。


圖 4-17:通過構造器來選擇域的對話方塊

將游標放到如下所示程式碼片段構造器的任何位置,並導航到Refactor ? Replace Constructor with Factory Method。結果對話方塊象圖4-18所示。點擊Refactor來產生一個Factory 方法。
public Sandbox(String shovel, int children) {
mShovel = shovel;
mChildren = children;
}


圖 4-18: 用原廠模式代替構造器的對話方塊

注意到之前的構造器現在變成private了並且一個新的靜態方法返回Sandbox類的執行個體,如下面程式碼片段所示。如果你正建立一個單例類,這將會是非常有用的。
public static Sandbox createSandbox(String shovel, int children) {
return new Sandbox(shovel, children);
}

Convert Anonymous to Inner  轉換匿名內部類

在你的Sandbox類的構造器裡加上下面行:
new Thread(new Runnable()).start();

把游標放在Runnable()上並按下Alt+Enter來調用完成代碼操作。然後選擇實現方法。選擇run()方法並點擊OK。你的代碼將象下面片段所示:
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的行為時你也許有機會用到這個。


圖 4-19: 轉換匿名內部類的對話方塊

Summary   小結

這章討論了Android Studio目前有效許多重構作業。重構代碼是編程工程的一個必需的部分,Android Studio裡的重構工具是最好的重構工具之一。Android Studio通過分析推理以及允許你於提交操作前在Find tool視窗預覽結果,減低了某些操作執行的風險。最重要的是重構作業Refactor ? Refactor This對話方塊是如此有效,這個可以通過用快速鍵Ctrl+Alt+Shift+T | Ctrl+T來調用。

 

[Learn Android Studio 漢化教程]第四章 : Refactoring Code

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.