这节课是 Android 开发(入门)课程 的第一部分《布局和交互》的第五节课,导师是 Katherine Kuan 和 Kunal Chawla,主要内容是 method 的定义和调用,对象的定义和对象 method 的调用。这节课的知识点比较多,有混淆难懂的地方可以参考 Android 词汇表,希望大家能耐心看下去,欢迎批评指正。
关键词:method、Android Resouces (AAPT→R Class)、onCreate、面向对象编程、Java Class(类)及其继承、Java Object(对象)、findViewById、Casting Object(类型转换)、Setter&Getter、Log(日志)
method 的定义和调用
-
类似变量,method 也是先定义后调用。针对重复使用的代码定义成 method,使程序模块化,就像造车,可以供人使用;在调用 method 时能精简代码,就像开车,无需了解汽车的工作原理。
-
类似制作蛋糕,method 通常有输入和输出,面粉和糖→输入,食谱→method 代码,蛋糕→输出。
-
程序运行到 method 调用处时,会跳到 method 定义处,由上至下执行 method 代码,最后返回 method 调用处。在 Android Studio 中,在 method 调用处单击 method 名,右键菜单中点击 Go To→Declaration (cmd+B),界面会跳到 method 定义处,逐级溯源可看到 Android 框架层源码。
-
定义 method 又称为方法签名 (Method Signature),Google 搜索 "define java method" 可找到 Oracle 的说明文档 。定义 method 有严格的格式规范:
Java访问修饰符 返回数据类型 method名(输入参数1数据类型 输入参数1变量名, 输入参数2数据类型 输入参数2变量名, ...) {
...
return 返回值;
}
(1)Java访问修饰符 (Access Modifier)
常见的有 private 和 public,private 指 method 只能在该 Activity 内被调用,public 则所有 Activity 都可以。
(2)返回数据类型 (Return Data Type)
method 的输出值称为返回值,此处定义 method 返回值的数据类型,如 int
, String
。无返回值时为 void
。
(3)method名 (Method Name)
在上面 Oracle 的说明文档中可找到 method 命名规范,动词开头,若是一个单词则全小写;若是多个单词则用小驼峰命名法。
(4)输入参数的格式:
数据类型 变量名
允许无输入或多个输入。通常无输入的情况是 method 内使用全局变量。输入参数用小括号包含,多个输入参数用逗号分隔,顺序不可调换。
(5)method 的代码用大括号包含,最后一行代码输出返回值 (return),在此之后的代码不被执行,在 Android Studio 中会对返回值之后的代码报错。
(6)输出返回值的格式:
return 返回值;
- return: Java 关键词,Google 搜索 "java keywords" 可找到Oracle的说明文档。int、new、private、public、void、this 等都属于 Java 关键词,他们不能用于标识符 (Identifiers),例如变量名和 method 名。
- 返回值:最多一个,注意匹配返回值数据类型。当无返回值 (void) 时则留空,即
return;
,但一般会把此行代码删去。 - 分号结束。
- 下面是定义 method 的一段代码实例。
/**
* Create summary of the order.
*
* @param price of the order
* @return text summary
*/
private String createOrderSummary(int price) {
return "Name:Kaptain Kunal" +
"\nQuantity:" + quantity +
"\nTotal: $" + price +
"\nThank you!";
}
(1)输入参数注释的格式:
@param 输入参数变量名 说明文字
(2)输出参数注释的格式:
@return 说明文字
此处无需写明输出参数是因为 method 最多只有一个返回值。
- 下面是调用 method 的一段代码实例。
/**
* This method is called when the order button is clicked.
*/
public void submitOrder(View view) {
int price = calculatePrice();
displayMessage(createOrderSummary(price));
}
(1)在调用 createOrderSummary 时,输入了变量 price,此处的输入参数称为实参 (Arguments),即 method 调用处传递给 method 的输入;相应地,method 定义处声明的输入参数则称为形参 (Input Parameters)。参数传递的概念可 Google 搜索 "java method parameter" 可找到 Oracle 的说明文档。
(2)method 可在运算中调用,参与运算的值为 method 的返回值;进一步将运算作为实参而不是声明一个新变量传递参数,可使代码更简洁。如
createOrderSummary(calculatePrice() + 3);
面向对象编程
-
Android App 主要分为资源文件(Resources,包括图片、音视频、XML 布局文件等)和 Java 代码两部分。这种分类能使 App 根据不同设备加载不同资源,而无需修改 Java 代码。
-
每个资源文件都有 ID,AAPT 生成 R class (R.java) 包含了这些 ID,使得资源可通过调用来获取。
(1)在 Java 中调用格式:R.资源类型.资源名
(2)在 XML 中调用格式:@资源类型/资源名
- 资源类型:图片 (drawable)、字符串 (string)、布局 (layout)、颜色 (color) 、尺寸 (dimen)、样式 (style) 等。
- 资源名:开发者自己定义的资源名称。
(1)Examples in Java files: R.drawable.photo, R.string.hello, R.layout.activity_main, R.id.price_text_view, R.color.red.
(2)Examples in XML files: @drawable/photo, @string/hello, @layout/activity_main, @id/price_text_view, @color/red, @dimen/viewgroups_padding, @style/MainActivityText.
- App 启动后首先执行 OnCreate method,其中
setContentView(R.layout.activity_main);
会读取布局资源文件(将 Layout 的 ID 输入该 method,这里即可指定 App 初始化后首先显示的 Layout);随后开始解析 (Inflate) Java 对象,对象组成 App 的多级 Views 集合;最后与对象交互,这就是面向对象编程 (Object Oriented Programming)。
对象的定义和对象 method 的调用
-
Java 对象可简单理解为多个变量的整合,例如 TextView 是一个对象,其中类似变量,声明 (state) 有许多字段 (field),如 int 字体大小,String 文本。
-
将对象的声明和 method 定义为 class (TextView.java),即定义 TextView 的规则,就像商品房的平面设计图。
(1)class 中定义了许多字段,即全局变量来保存对象的属性,名称以 m 开头 (member variable)。
(2)class 中定义了许多 method 来操作字段,供 Android 调用。
安装 Chrome 插件 Android SDK Search 可在 Android 文档标题右侧添加 (view source) 链接,可点击打开相应的 Android 源码。开发者无需了解 class 也可使用对象。 -
定义对象,又称为对象实例 (Object Instance),是一个对象的具体实现,就像将商品房的平面设计图建造成实际的房子。
定义对象有严格的格式规范:
对象数据类型 变量名 = 初始值;
(1)对象数据类型:class 名,如 TextView。对象数据类型可自定义。
(2)变量名:定义对象的名称,遵循变量命名规则,如 textView。
(3)初始值:两种方式:构造函数(常用)和工厂法。
-
构造函数 (Constructor):
new 对象数据类型(输入参数); new TextView(content);
小括号内为输入语境,用来获取资源和运行环境。输入参数可在 class 源文件找到。
-
工厂法 (Factory Methods):
对象数据类型.工厂method名(输入参数);
工厂 method 名和对应的输入参数可在 Android 文档中找到。如
Toast toastMessage = Toast.makeText(content, "Hi", duration);
善用 Google 搜索如何新建对象。针对 TextView、ImageView、Button 等对象,他们在 XML 出现时就相当于在 Java 中新建了对应的对象,所以可以通过 findViewById 等 method 直接调用,无需再写新建语句。
-
调用对象的 method:
对象变量名.method名(输入参数);
(1)对象变量名 (Object Variable Name):注意不是对象数据类型。
-
在 class 内调用:如
this.setText(“Hello”);
this 指向当前 Activity,可省略。可读取 class 的 private 变量和方法。
-
在 class 外调用:如
textView.setText(“Hello”);
textView 为对象变量名。只能读取 class 的 public 变量和方法。
(2)method 名 (Method Name): 对应对象数据类型的 method。
(3)输入参数 (Input Arguments): 注意顺序和数据类型。
其他概念
- class 的继承行为
public class MainActivity extends AppCompatActivity {
AppCompatActivity(旧版本为 ActionBarActivity)属于 Android Support Library,作用是让旧设备也能使用新 UI。此处将 MainActivity 作为 AppCompatActivity 的功能扩展,即使 MainActivity 能使用 AppCompatActivity 的所有声明和 method,如 setContentView 和 findViewById。
MainActivity 选择不继承 AppCompatActivity 的 method 时可通过 @override
标记来重写 method ,但仍可以继承其他 method。例如下面的 onCreate 函数通过 override 使用继承的 setContentView 方法设置了 App 初始化后显示的 Layout。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
从 class 层次图 (Class Inheritance) 的观点来看,AppCompatActivity 为父 class (Superclass),MainActivity 为子 class (Subclass)。例如 TextView、ImageView 和 Button 把三者相同的属性取出定义为 View class,则 View 为父 class (View.java),TextView 为子 class (TextView.java),他们之间用继承关系连接。这种结构体现了 Android 的层次性。
- 类型转换 (Casting Objects)
Java 通过 ID 来连接资源,并将这些对象保存为 class 的成员变量。findViewById 返回 View 的子类时就需要类型转换
(Casting Objects),善用 Google 搜索和开发文档,熟悉不同方法对应的返回值类型和对应的 Java 类 (class)。转换的类型需要符合数据类型。
TextView orderSummaryTextView = (TextView) findViewById(R.id.order_summary_text_view);
(1)(TextView) 将 findViewById 返回的 View class 转换为 TextView,与左侧的数据类型一致。
(2)Google 搜索 "textview android" 可找到 TextView 的 Android 文档,用浏览器可搜索到不同 method 的返回值类型。
(3)当仅使用父 class 的 method 时,无需转换成子 class 来操作。
从 API 26 开始,findViewById 的返回数据类型已由 View
更新为 <T extends View>
(T 指“类型”,属于 Java 的泛型类型 (Generic Type),后续课程后介绍),因此若 compileSdk
为 API 26 以上,则 findViewById 无需再进行类型转换。
- Setter & Getter
orderSummaryTextView.setText("" + message);
例如 setText 和 setImageResource。这些叫做 setter method,因为它们负责修改或操控视图的某个值(例如视图存储的文本或图片)。按照惯例,它们以 "set" 开头。
还有一种类别的 method,叫做 getter method,它们的唯一目的是从视图中“获取”值,例如获取视图的当前文本。按照惯例,它们以 "get" 开头。
Android Studio 的 Log 日志
Log.i("EnterpriseActivity.java", "Captain's Log, Stardate 43125.8. We have entered a spectacular binary star system in the Kavis Alpha sector on a most critical mission of astrophysical research.");
第一个参数是日志语句所来自的 class 名称。第二个参数是想要显示的文字。这里使用了 Log.i()
,表示“信息”级别的日志。其他级别的选项如下:
- 错误:Log.e(String, String)
- 警告:Log.w(String, String)
- 信息:Log.i(String, String)
- 调试:Log.d(String, String)
- 详情:Log.v(String, String)
它们对应的是不同的日志级别,运行应用时可以根据分类查看。
网友评论