代碼重構幾乎是每個程序員在軟件開發中必須要不斷去做的事情,以此來不斷提高代碼的質量。Android Stido(以下簡稱AS)以其強大的功能,成為當下Android開發工程師最受歡迎的開發工具,也是Android官方推薦使用的工具。如此優秀的工具,自然少不了要在代碼重構這件事情上好好表現一把了。本文將通過代碼演示,功能截圖來詳細介紹AS為代碼重構提供的各項功能。
在AS的主菜單欄中有一項“Refactor”下拉菜單,點擊該下拉菜單,會看到如下的界面,菜單中的每一項,都是為代碼重構提供的一項自動實現功能。這么多的功能項,可見AS在代碼重構功能上的強大,下面我們對這些功能項一一進行介紹。另外,還可以在編輯界面中點擊右鍵,在彈出的菜單中也可以找到“Refactor”。

1、Refactor This
作用:重構當前。操作此項,會顯示對當前光標選中處可行的重構方法。
示例:選擇了類名“RefactorTest”,操作“Refactor This”后,顯示了可執行的重構方法列表,可以通過選擇數字來執行對應的方法。

2、Rename
作用:對光標選中項進行重命名。不僅可以對類中的成員變量進行重命名,還能對文件名,包名等進行重命名,Module中與之相關聯的所有地方都會一起修改,而不用一一手動修改。
快捷鍵:Shift + F6
示例:在紅框中輸入修改后的名稱,并按Enter鍵即可。

3、Rename File
作用:修改當前編輯界面顯示的文件的文件名。就相當于鼠標選中該文件,并執行“Rename”方法。
示例:在顯示的對話框中輸入新文件名??梢栽谙路降倪x項框中選擇修改范圍,引用該文件的地方,注釋,字符串中都可以選擇一起修改。

4、Change Signature
作用:修改方法、類、構造函數的簽名,其實就是修改所選項的一些屬性。
快捷鍵:Ctr l+ F6
示例:如下展示了一個方法重構前,重構過程,以及重構后的情形(以修改一個方法簽名為例)。
重構前:
private void testChangeSignature(int first, int second) {
}
選中方法名后,執行該重構方法后,會彈出如下對話框,可以對該方法各種屬性進行修改,添加/刪除參數,調整參數順序,新增/刪除異常等。

重構后:
public void testChangeSignature(int second, int first, String third) throws NullPointerException {
}
5、Type Migration
作用:類型遷移,即對變量數據類型,或者方法的返回類型進行修改。前面介紹了對文件名,包名,變量名等進行修改,這里對類型進行修改。
快捷鍵:Ctrl + Shift + F6
重構前:
private int age = 10;
public RefactorTest(int age) {
this.age = age;
}
選中要修改的類型,執行該重構方法,會彈出對話框,根據需要編輯類型,選中作用范圍即可。指定范圍內,與該變量相關聯處都會被修改。

重構后(由于從int修改到String,所以還需要手動修改變量值):
private String age = "10";
public RefactorTest(String age) {
this.age = age;
}
6、Make Static
作用:給內部類或者方法添加static關鍵字。示例比較簡單,就不做演示了。
7、Convert To Instance Method
作用: 轉換為實例方法,即將靜態方法去掉static關鍵字。
8、Move
功能:移動文件到指定路徑
快捷鍵:F6

9、Copy
作用:在指定包中拷貝一份當前文件
快捷鍵:F5

10、Safe Detele
作用:安全刪除,可用于對方法/字段等進行快速刪除,會刪除掉與之相關聯的引用。
快捷鍵:Alt + Delete



11、Extract
(1)Variable
作用:提取變量。這一點在碰到比較長的表達式時經常用到,將看起來很長很復雜的表達式提取出來作為一個變量表示。
快捷鍵:Ctrl + Alt + V
重構前:我們常會看到這樣的代碼
public void testExtractVariable() {
Log.i("demo", "age=" + getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge() + ";name=" + getNnnnnnnnnnnnnnnnnnnnnnname());
}
private int getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge() {
return age;
}
private String getNnnnnnnnnnnnnnnnnnnnnnname() {
return name;
}
第二行的要打印的信息表達式太長了,希望單獨提取出來用一個變量表示。本示例中鼠標停留在第2行“getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge”處,執行該重構方法,會彈出如下紅框部分對話框,顯示的是選中表達式相關的可提取部分,根據需要選擇要提取的部分即可。

重構后:
public void testExtractVariable() {
String msg = "age=" + getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge() + ";name=" + getNnnnnnnnnnnnnnnnnnnnnnname();
Log.i("demo", msg);
}
private int getAaaaaaaaaaaaaaaaaaaaaaaaaaaAge() {
return age;
}
private String getNnnnnnnnnnnnnnnnnnnnnnname() {
return name;
}
(2)Constant
作用:提取常量,將表達式中的值提取為常量。
快捷鍵:Ctrl + Alt +C
重構前:
public void testExtractConstant() {
String filename = "sdcard";
}

重構后:
public static final String SDCARD = "sdcard";
public void testExtractConstant() {
String filename = SDCARD;
}
(3)Filed
作用:提取字段,將局部變量提取為全局變量。
快捷鍵:Ctrl + Alt +F
重構前:
public void testExtractField() {
String name ="zhangsan";
}

重構后:
private final String string = "zhangsan";
public void testExtractField() {
}
(4)Parameter
作用:將局部變量提取為方法的參數。
快捷鍵:Ctrl + Alt +P
重構前:
public void testExtractParameter() {
printName();
}
private void printName(){
String name = "zhangsan";
Log.i("demo","My name is:"+name);
}

重構后:
public void testExtractParameter() {
printName("zhangsan");
}
private void printName(String name){
Log.i("demo","My name is:"+ name);
}
(5)Functional Parameter ( 函數式參數 )Ctrl + Alt + Shift + P
(6)Parameter Object
作用:將參數提取為一個對象。該功能主要是針對參數比較多的時候,將這些參數提取出來作為一個Bean實例傳入。
重構前:
private void testExtractParamObject() {
String info = getInfo("zhangshan", 20, 180f);
}
private String getInfo(String name, int age, float height) {
return "name=" + name + ";age=" + age + ";height=" + height;
}

重構后:
private void testExtractParamObject() {
String info = getInfo(new Person("zhangshan", 20, 180f));
}
private String getInfo(Person person) {
return "name=" + person.getName() + ";age=" + person.getAge() + ";height=" + person.getHeight();
}
private static class Person {
private final String name;
private final int age;
private final float height;
private Person(String name, int age, float height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public float getHeight() {
return height;
}
}
(7)Mehtod
作用:提取為方法
快捷鍵:Ctrl + Alt +M
重構前:
public void testExtractMethod() {
List<String> nameList = new ArrayList<>();
nameList.add("zhangshan");
nameList.add("lisi");
nameList.add("wangwu");
int size = nameList.size();
}
鼠標光標選中第2~5行后執行該重構方法

重構后:
public void testExtractMethod() {
List<String> nameList = getNameList();
int size = nameList.size();
}
@NonNull
private List<String> getNameList() {
List<String> nameList = new ArrayList<>();
nameList.add("zhangshan");
nameList.add("lisi");
nameList.add("wangwu");
return nameList;
}
(8)Type Parameter
(9)Method Object
作用:將該選中的內容提取為一個方法,并提取到一個獨立的類中。和“Method”很類似,不同的是提取的方法最后放在哪里。
重構前:
public void testExtractMethod() {
List<String> nameList = new ArrayList<>();
nameList.add("zhangshan");
nameList.add("lisi");
nameList.add("wangwu");
int size = nameList.size();
}

重構后:
public void testExtractMethod() {
List<String> nameList = Utils.invoke();
int size = nameList.size();
}
private static class Utils {
private static List<String> invoke() {
List<String> nameList = new ArrayList<>();
nameList.add("zhangshan");
nameList.add("lisi");
nameList.add("wangwu");
return nameList;
}
}
(10)Delegate
作用:提取為一個代理類。
重構前:
public class RefactorTest{
public void testExtractInterface() {
System.out.print("testExtractInterface");
}
}

重構后:
public class RefactorTestDelegate {
public RefactorTestDelegate() {
}
public void testExtractInterface() {
System.out.print("testExtractInterface");
}
}
public class RefactorTest{
private final RefactorTestDelegate refactorTestDelegate = new RefactorTestDelegate();
public void testExtractInterface() {
refactorTestDelegate.testExtractInterface();
}
}
(11)Interrface
作用:提取為接口。
重構前:
public class RefactorTest {
public void testExtractInterface() {
System.out.print("testExtractInterface");
}
}
public修飾的方法才可以被提取到接口中。

重構后:
interface IRefactorTest {
void testExtractInterface();
}
public class RefactorTest implements IRefactorTest {
@Override
public void testExtractInterface() {
System.out.print("testExtractInterface");
}
}
(12)Superclass
作用:將指定內容提取到父類中。
重構前:
private void testExtractSupperclass() {
testSuper();
}
public void testSuper() {
System.out.print("testSuper");
}

重構后:
//=======RefactorTest extends RefactorTestBase=======
private void testExtractSupperclass() {
testSuper();
}
class RefactorTestBase {
public void testSuper() {
System.out.print("testSuper");
}
}
12、Inline
作用:轉換為內聯、方法鏈形式的調用。
快捷鍵:Ctrl + Alt +N
重構前:
private void testInline() {
int a = 100;
int b = 200;
System.out.print(add(a, b));
}
private int add(int a, int b) {
System.out.print("a=" + a + ";b=" + b);
return a*2 + b*3;
}

重構后:
private void testInline() {
int a = 100;
int b = 200;
System.out.print("a=" + a + ";b=" + b);
System.out.print(a * 2 + b * 3);
}
原先需要調用一個方法,重構后直接把該方法中的代碼給復制過來了。因為上面選中的是內聯所有的,并且刪除該方法,所以add方法也就被刪除了。
13、Find and Replace Code Duplicates
14、Invert Boolean
作用:轉換Boolean值,將當前false/true的值進行轉化為相反的值。
重構前:
private boolean isEmpty(String str) {
if (str != null && str.length() == 0) {
return false;
}
return true;
}

重構后:
private boolean isNotEmpty(String str) {
if (str != null && str.length() == 0) {
return true;
}
return false;
}
15、Pull Members Up
作用:將子類的成員上移到父類中。
重構前:
public class RefactorBase {
}
public class RafactorSub extends RefactorBase {
int age = 10;
public void printSub() {
System.out.print(age);
}
}

重構后:
public class RefactorBase {
int age = 10;
public void printSub() {
System.out.print(age);
}
}
public class RafactorSub extends RefactorBase {
}
16、Push Members Down
作用:將父類中的成員下移到子類中,正好是“Pull Members Up”的反向操作。
重構前:
public class RefactorBase {
int age = 10;
public void printSub() {
System.out.print(age);
}
}
public class RafactorSub extends RefactorBase {
}

重構后:
public class RefactorBase {
}
public class RafactorSub extends RefactorBase {
int age = 10;
public void printSub() {
System.out.print(age);
}
}
17、Use Interface Where Possible
18、Replace Inheritance with Delegation
作用:使用代理替代繼承。在java中,提倡使用組合,而不是繼承。
重構前:
public abstract class AbsClass {
public abstract void print();
}
public class ClassWrapper extends AbsClass {
@Override
public void print() {
System.out.print("print");
}
}
private void testReplaceInheritanceWithDelegation() {
new ClassWrapper().print();
}

重構后:
public abstract class AbsClass {
public abstract void print();
}
public class ClassWrapper {
private final ClassImpl absClass = new ClassImpl();
public void print() {
absClass.print();
}
private class ClassImpl extends AbsClass {
@Override
public void print() {
System.out.print("print");
}
}
}
public class RefactorTest {
private void testReplaceInheritanceWithDelegation() {
new ClassWrapper().print();
}
}
這一部分有點像Android中Context,ContextWrapper,ContextImpl類之間的關系。
19、Remove Middleman
作用:移除中間人,其實就是移除中間過程。
重構前:
public class RefactorTest {
private void testRemoveMiddleMan() {
BookManager bookManager = new BookManager();
bookManager.addBook("java");
}
public static class BookManager {
private List<String> mBookList = new ArrayList<>();
private void addBook(String bookName) {
mBookList.add(bookName);
}
}
}

重構后:
public class RefactorTest {
private void testRemoveMiddleMan() {
BookManager bookManager = new BookManager();
bookManager.getmBookList().add("java");
}
public static class BookManager {
private List<String> mBookList = new ArrayList<>();
public List<String> getmBookList() {
return mBookList;
}
}
}
對比重構前和重構后會發現,添加book這個動作,從由BookManager的addBook方法來執行,變成了直接有mBookList來執行了。這個addBook就是這個MiddleMan,顯得多余,可以優化掉。實際上優化后就變成一個inline方式了,可以對比前面講到的“Inline”。
20、Wrap Method Return Value
作用:封裝返回值
public class RefactorTest {
private void testWrapReturnValue() {
String name = getName();
}
private String getName() {
return "zhangsan";
}
}

重構后:
public class RefactorTest {
private void testWrapReturnValue() {
String name = getName().getValue();
}
private Person getName() {
return new Person("zhangsan");
}
public class Person {
private final String value;
public Person(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
21、Convert Anonymous to Inner
作用:將匿名內部類轉為內部類。
重構前:
private void testConvertAnonymousToInner(){
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}

重構后:
public class RefactorTest{
View view;
private void testConvertAnonymousToInner(){
view.setOnClickListener(new MyOnClickListener());
}
private static class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
}
}
}
22、Encapsulate Fields
作用:封裝字段,用于生成Getter/Setter
重構前:
public String name = "zhangsan";
private void testEncapsulateFields() {
System.out.println(name);
}

通過該對話框,可以選擇要封裝的字段,設置修飾符等。默認選擇時,name字段的修飾符從public變成了private,這也就避免了外部類通過實例直接訪問它。
重構后:
private String name = "zhangsan";
private void testEncapsulateFields() {
System.out.println(getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
23、Replace Temp With Query
24、Replace Constructor with Factory Method
作用:將構造方法替換為工廠方法
重構前:
public class MyClass {
private String title;
private String message;
private String sure;
private String cancel;
public MyClass(String title, String message, String sure, String cancel) {
this.title = title;
this.message = message;
this.sure = sure;
this.cancel = cancel;
}
}
public class RefactorTest {
private void testReplaceConstructorWithFactory(Context context) {
MyClass myClass = new MyClass("title", "message", "sure", "cancle");
}
}

重構后:
public class MyClass {
private String title;
private String message;
private String sure;
private String cancel;
private MyClass(String title, String message, String sure, String cancel) {
this.title = title;
this.message = message;
this.sure = sure;
this.cancel = cancel;
}
public static MyClass createMyClass(String title, String message, String sure, String cancel) {
return new MyClass(title, message, sure, cancel);
}
}
public class RefactorTest {
private void testReplaceConstructorWithFactory(Context context) {
MyClass myClass = MyClass.createMyClass("title", "message", "sure", "cancle");
}
}
原先public修飾的構造函數,已經變成private了,MyClass類只能通過工廠方法來獲取實例,而無法再直接new了。
25、Replace Constructor with Builder
作用:將構造方法替換為Builder方式
重構前:
public class RefactorTest{
private void testReplaceConstructorWithBuilder(Context context){
MyDialog dialog = new MyDialog(context,"title","message","sure","cancle");
}
}
public class MyDialog extends Dialog {
private String title;
private String message;
private String sure;
private String cancel;
public MyDialog(@NonNull Context context) {
super(context);
}
public MyDialog(Context context, String title, String message, String sure, String cancel) {
super(context);
this.title = title;
this.message = message;
this.sure = sure;
this.cancel = cancel;
}
}

重構后:
public class RefactorTest {
private void testReplaceConstructorWithBuilder(Context context) {
MyDialog dialog = new MyDialogBuilder()
.setContext(context)
.setTitle("title")
.setMessage("message")
.setSure("sure")
.setCancel("cancle")
.createMyDialog();
}
}
public class MyDialogBuilder {
private Context context;
private String title;
private String message;
private String sure;
private String cancel;
public MyDialogBuilder setContext(Context context) {
this.context = context;
return this;
}
public MyDialogBuilder setTitle(String title) {
this.title = title;
return this;
}
public MyDialogBuilder setMessage(String message) {
this.message = message;
return this;
}
public MyDialogBuilder setSure(String sure) {
this.sure = sure;
return this;
}
public MyDialogBuilder setCancel(String cancel) {
this.cancel = cancel;
return this;
}
public MyDialog createMyDialog() {
return new MyDialog(context);
}
}
看到這里,我們應該能夠聯想到AlertDialog類中的Builder了。將構造函數的形式,轉變為了建造者模式的形式,這樣不會拘泥于構造函數的參數個數,參數類型的限制,從而靈活設置屬性。
26、Generify
作用:泛型重構,自動添加泛型的參數。
重構前:
private void testGenerify() {
List list = new ArrayList();
list.add("one");
list.add("two");
list.add("three");
}

重構后:
private void testGenerify() {
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
}
27、Migrate
28、Internationalize(國際化)
29、Remove Unused Resources
作用:一直不用的資源
示例:下圖中1.jpg是一個沒有被應用的文件。


在執行該重構方法后,1.jpg就被刪除了。

總結
以上所述是小編給大家介紹的AndroidStudio中代碼重構菜單Refactor功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。