Android Studio是基于优秀的ide的,ide提供了丰富的功能,很方便的对代码进行重构,下图是我的Android Studio Refactor菜单,部分快捷键与默认快捷键不同是因为方便而修改的。
如何使用
鼠标光标选中或者放在代码上,按下快捷键就可以弹出当前代码可以使用的功能。
如下所示:
- ChangeSignature,改变函数签名,可以修改函数的名字,参数的顺序,参数的名字。
Before:
// 改变签名
void testChangeSignature(int second, int first) {
System.out.println(first + "->" + second);
}
After:
// 改变签名
void testChangeSignature(int one, int two) {
System.out.println(one + "->" + two);
}
修改前参数依次是second、first,修改是one、two。
- 修改匿名类为内部类
Before:
// 匿名类改成内部类
void testConvertAnonymousToInner() {
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("onClick");
}
};
}
Gif:
After:
// 匿名类改成内部类
void testConvertAnonymousToInner() {
View.OnClickListener clickListener = new Abc123();
}
private static class Abc123 implements View.OnClickListener {
@Override
public void onClick(View v) {
System.out.println("onClick");
}
}
- Copy,复制一个类
Before:
// 复制一个类
void testCopy() {
new FirstClass();
}
public class FirstClass implements Serializable {
public String first;
@Override
public String toString() {
return "FirstClass{" +
"first='" + first + '\'' +
'}';
}
}
Gif:
After:
public class SecondClass implements Serializable {
public String first;
@Override
public String toString() {
return "SecondClass{" +
"first='" + first + '\'' +
'}';
}
}
- InvertBoolean,重构Boolean
Before:
// 重构Boolean
void testInvertBoolean() {
System.out.println(checkPaswd(null));
System.out.println(checkPaswd(""));
System.out.println(checkPaswd("admin"));
}
boolean checkPaswd(String passwd) {
if (passwd != null && passwd.length() != 0) {
return true;
}
return false;
}
Gif:
After:
// 重构Boolean
void testInvertBoolean() {
System.out.println(checkPaswd(null));
System.out.println(checkPaswd(""));
System.out.println(checkPaswd("admin"));
}
boolean checkPaswd(String passwd) {
return passwd != null && passwd.length() != 0;
}
- ReplaceConstructorWithBuilder,构造方法变成builder
还在羡慕Picasso,Fresco人性化调用方式吗?很简单,通过这个功能就可以快速生成代码
Before:
public class MyAlertDialog {
private String title;
private String message;
private String okButton;
private String cancelButton;
public MyAlertDialog(String title, String message, String okButton, String cancelButton) {
this.title = title;
this.message = message;
this.okButton = okButton;
this.cancelButton = cancelButton;
}
}
// 构造方法变成builder
void testReplaceConstructorWithBuilder() {
new MyAlertDialog("title", "message", "ok", "cancel").show();
}
Gif:
After:
// 构造方法变成builder
void testReplaceConstructorWithBuilder() {
new MyAlertDialog.Builder()
.setTitle("title")
.setMessage("message")
.setOkButton("ok")
.setCancelButton("cancel")
.createMyAlertDialog()
.show();
}
public static class Builder {
private String title;
private String message;
private String okButton;
private String cancelButton;
public Builder setTitle(String title) {
this.title = title;
return this;
}
public Builder setMessage(String message) {
this.message = message;
return this;
}
public Builder setOkButton(String okButton) {
this.okButton = okButton;
return this;
}
public Builder setCancelButton(String cancelButton) {
this.cancelButton = cancelButton;
return this;
}
public MyAlertDialog createMyAlertDialog() {
return new MyAlertDialog(title, message, okButton, cancelButton);
}
}
- ReplaceConstructorWithFactory,构造方法变成工程方法
Before:
// 构造方法变成工程方法
void testReplaceConstructorWithFactory() {
new MyAlertDialog("title", "message", "ok", "cancel").show();
}
- 1
- 2
- 3
- 4
Gif:
After:
// 构造方法变成工程方法
void testReplaceConstructorWithFactory() {
MyAlertDialog.newInstance("title", "message", "ok", "cancel")
.show();
}
public class MyAlertDialog {
private MyAlertDialog(String title, String message, String okButton, String cancelButton) {
this.title = title;
this.message = message;
this.okButton = okButton;
this.cancelButton = cancelButton;
}
public static MyAlertDialog newInstance(String title, String message, String okButton, String cancelButton) {
return new MyAlertDialog(title, message, okButton, cancelButton);
}
}
通过上面代码发现,如果构造方法变成了工厂方式,那么它的构造参数是private的,这样调用者只能通过工厂方式来生成对象。
代码抽取
- ExtractParameterObject,抽取若干参数成一个类
这个比较使用,有时候一个方法参数太多,可以把这些参数合并成一个类。
Before:
// 抽取若干参数成一个类
void testExtractParameterObject() {
print(100, 200);
}
// widht,height --> Size Class
void print(int width, int height) {
System.out.println("width = " + width + ", height = " + height);
}
Gif:
After:
// 抽取若干参数成一个类
void testExtractParameterObject() {
print(new Size(100, 200));
}
// widht,height --> Size Class
void print(Size size) {
System.out.println("width = " + size.getWidth() + ", height = " + size.getHeight());
}
public class Size {
private final int width;
private final int height;
public Size(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
- ExtractSuperclass,抽取到父类
Before:
// 抽取到父类
void testExtractSuperclass() {
sendEvent("login_success");
}
public void sendEvent(Object event) {
// EventBus.getDefault().send(event);
}
Gif:
After:
public class BaseExtractDemo {
public void sendEvent(Object event) {
// EventBus.getDefault().send(event);
}
}
public class ExtractDemo extends BaseExtractDemo {
// 抽取到父类
void testExtractSuperclass() {
sendEvent("login_success");
}
}
综合示例
通过一个示例演示怎么样重构代码,示例是一个Activity里面有个RecyclerView,然后重构代码,演示怎么样分离Adapter,ViewHolder等。
Before:
public class StartActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
final List<String> data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
data.add("Text " + (i + 1));
}
recyclerView.setAdapter(new RecyclerView.Adapter<MyViewHolder>() {
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return new MyViewHolder(layoutInflater.inflate(android.R.layout.simple_list_item_1, parent, false));
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.bind(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
});
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(android.R.id.text1);
}
void bind(String text) {
textView.setText(text);
}
}
}
Gif:
After:
public class StartActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<String> data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initData();
initView();
}
private void initData() {
data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
data.add("Text " + (i + 1));
}
}
private void initView() {
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new MyViewHolderAdapter(data));
}
}
class MyViewHolderAdapter extends RecyclerView.Adapter<MyViewHolder> {
private List<String> data;
public MyViewHolderAdapter(List<String> data) {
this.data = data;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return MyViewHolder.newInstance(parent);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.bind(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
public static final int LAYOUT_ID = android.R.layout.simple_list_item_1;
@NonNull
static MyViewHolder newInstance(ViewGroup parent) {
Context context = parent.getContext();
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return new MyViewHolder(layoutInflater.inflate(LAYOUT_ID, parent, false));
}
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(android.R.id.text1);
}
void bind(String text) {
textView.setText(text);
}
}