转载请声明,转载自【https://www.cnblogs.com/andy-songwei/p/11809700.html】,谢谢!

代码重构几乎是每个程序员在软件开发中必须要不断去做的事情,以此来不断提高代码的质量。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”方法。

示例:在显示的对话框中输入新文件名。可以在下方的选项框中选择修改范围,引用该文件的地方,注释,字符串中都可以选择一起修改。

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");
}
}

(13) Style

作用:将属性提取为Style。该项只有当鼠标停留在布局文件中时才会出现。

重构前:

 <Button
android:id="@+id/btn_handler_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler" />

重构后:

 <Button
android:id="@+id/btn_handler_demo"
android:text="handler"
style="@style/testStyle" />

styles.xml

 <?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="testStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
</resources>

(14)Layout

作用:提取为布局文件。这一项也是需要在鼠标停留在布局文件中时才会出现。

 <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_handler_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="handler" />
<Button
android:id="@+id/btn_broadcast_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Broadcast" />
<Button
android:id="@+id/btn_bright_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bright" />
<Button
android:id="@+id/btn_service_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Service" />
</LinearLayout>

重构后:

<include layout="@layout/testlayout" />

testlayout.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:showIn="@layout/activity_main"> <Button
android:id="@+id/btn_preference_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Preference" /> <Button
android:id="@+id/btn_file_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="File" /> <Button
android:id="@+id/btn_anim_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Anim" /> <Button
android:id="@+id/btn_customview_demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CustomView" />
</LinearLayout>

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就被删除了。

参考:https://www.jianshu.com/p/f8cb51bc8e19

【重构】AndroidStudio中代码重构菜单Refactor功能详解的更多相关文章

  1. 在ASP.NET 5应用程序中的跨域请求功能详解

    在ASP.NET 5应用程序中的跨域请求功能详解 浏览器安全阻止了一个网页中向另外一个域提交请求,这个限制叫做同域策咯(same-origin policy),这组织了一个恶意网站从另外一个网站读取敏 ...

  2. Python中pandas透视表pivot_table功能详解(非常简单易懂)

    一文看懂pandas的透视表pivot_table 一.概述 1.1 什么是透视表? 透视表是一种可以对数据动态排布并且分类汇总的表格格式.或许大多数人都在Excel使用过数据透视表,也体会到它的强大 ...

  3. React在开发中的常用结构以及功能详解

    一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...

  4. .NET重构—单元测试的代码重构

    阅读目录: 1.开篇介绍 2.单元测试.测试用例代码重复问题(大量使用重复的Mock对象及测试数据) 2.1.单元测试的继承体系(利用超类来减少Mock对象的使用) 2.1.1.公用的MOCK对象: ...

  5. iOS之UI--使用SWRevealViewController实现侧边菜单功能详解实例

    使用SWRevealViewController实现侧边菜单功能详解 下面通过两种方法详解SWRevealViewController实现侧边菜单功能: 1.使用StoryBoard实现   2.纯代 ...

  6. iOS之UI--使用SWRevealViewController 实现侧边菜单功能详解实例

     iOS之UI--使用SWRevealViewController 实现侧边菜单功能详解实例 使用SWRevealViewController实现侧边菜单功能详解 下面通过两种方法详解SWReveal ...

  7. UIViewController中各方法调用顺序及功能详解

    UIViewController中各方法调用顺序及功能详解 UIViewController中loadView, viewDidLoad, viewWillUnload, viewDidUnload, ...

  8. 教程-Delphi中Spcomm使用属性及用法详解

    Delphi中Spcomm使用属性及用法详解 Delphi是一种具有 功能强大.简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选 ...

  9. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

随机推荐

  1. 【ADO.NET基础-Regidter】简单的账户注册界面和源代码(可用于简单面试基础学习用)

    在阅读时如有问题或者建议,欢迎指出和提问,我也是初学者......... 前台代码: <!DOCTYPE html> <html xmlns="http://www.w3. ...

  2. CMD的最佳“代替品”

    让CMD成为历史 Windows用户大多都使用过"cmd",cmd被称为"阉割版"的DOS系统~ 很多用户除此之外,还喜欢Linux命令行~但是CMD的命令和L ...

  3. JavaScript实现各种排序算法

    前言:本文主要是用JavaScript实现数据结构中的各种排序算法,例如:插入排序.希尔排序.合并排序等. 冒泡排序 function bubbleSort(arr) { console.time(& ...

  4. 并发编程的模型分类(转载于https://link.zhihu.com/?target=http%3A//www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/)强烈推荐!

    在并发编程需要处理的两个关键问题是:线程之间如何通信 和 线程之间如何同步. 通信 通信 是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存 和 消息传递. 在共享内 ...

  5. vue运行报错webpack-dev-server: command not found

    翻译过来就是: 'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 解决方法: 然后总结下成功的步骤: 1. 直接在项目目录下: cnpm install npm run ...

  6. 你也可以写聊天程序 - C# Socket学习1

    简述 我们做软件工作的虽然每天都离不开网络,可网络协议细节却不是每个人都会接触和深入了解.我今天就来和大家一起学习下Socket,并写一个简单的聊天程序. 一些基础类 首先我们每天打开浏览器访问网页信 ...

  7. Jenkins项目构建

    一:新建项目 (1)点击新建,输入项目名称--构建一个自由风格的软件项目,点击ok (2)创建项目名称,选择节点标签 (3)构建触发器-----设置每两分钟执行一次 其中有5个参数 (*****) 第 ...

  8. Bran的内核开发教程(bkerndev)-04 创建main函数和链接C文件

    目录 创建main函数和链接C文件 PS: 下面是我自己写的 Win10安装gcc编译器 本节教程对应的Linux下的编译脚本 _main的问题 创建main函数和链接C文件   一般C语言使用mai ...

  9. caffe中softmax loss源码阅读

    (1) softmax loss <1> softmax loss的函数形式为:     (1) zi为softmax的输入,f(zi)为softmax的输出. <2> sof ...

  10. React+Antd+Antd-Img-Crop实现上传固定大小的裁剪头像或者图片(且可控制图片数量)

    见章知著 1024,程序员们节日快乐!本文主要讲述react配合antd以及react-img-crop第三方库实现一个可控的图片上传功能. 运行项目 需要具有node环境 第三方库安装 1.antd ...