5.1 在Activity中创建界面
Activity虽然代表一个页面,但是它却不是View,然而它却能管理View们。我们可以使用代码将一个Activity上的控件们创建出来并摆放好来构成Activity的界面,但是太麻烦,以后的改动也非常难,所以通常都是在layout资源中定义Activity的界面。App在显示一个Activity前,会把Layout中定义界面创建出来,设置给Activity,之后再把Activity显示出来,这样我们就看到了Activity的样子,所以Activity的内容是由它里面的控件们组合出来的。
实际上从layout资源创建界面并设置给Activity这件事,App并不会自动做,需要我们写代码完成,只需要调用Acitivity的一个方法setContentView()即可。这个方法需要一个参数,就是layout资源文件的id。这个方法需要在什么时机调用呢?应在Activity被创建之后,但还未显示出来之前调用。最适合的地方就是Activity的onCreate()方法。打开你的MainActivity类看一下,是不是有onCreate()方法,如图5.1.1所示。
图5.1.1
并且setContentView()方法是不是被调用了?在onCreate()方法被调用之后经过不长的时间,Activity就被显示出来,由于显示之前已把控件都创建并加载了,所以我们就看到了Activity的界面。当然这些代码Android Studio已帮我们添加了,所以不需要我们手动编写了,但它们也不是SDK中的类封装好的,所以还是相当于我们手动添加的。
5.1.1 类R
setContentView()的实参是R.layout.activity_main,它是一个整数常量,它是layout型资源文件activity_main.xml的id。R是一个类,是Gradle处理项目中的资源文件后自动产生的,我们不能改动它的内容。可以看到layout资源文件的id名与文件名相同,而文件的扩展名被忽略。既然文件名要成为类中常量的名字,所以文件名当然不能以数字开头了。
资源id一般是这样命名的:“R.资源类型.id名”,比如引用一个资源中定义的字符串,如果其id为“xxx”,就用“R.string.xxx”;引用一个图片(其id也为“xxx”),就用“R.drawable.xxx”,而引用layout资源(比如activity_main.xml)中的某个控件时(控件id也为“xxx”),就用“R.id.xxx”。总之,如果引用的是一个资源文件,“R”后面是其类别;如果是资源中的一个元素(比如layout资源中的一个控件),“R”后面是“id”。
5.1.2 Activity的父类
所有Activity的祖宗是类Activity。但我们看到MainActivity类的父类是AppCompatActivity。AppCompatActivity当然也是从Activity类派生的,它对旧版本Android系统的兼容性好,所以现在推荐此类为我们定义的Activity的父类,这样你的App才有可能运行在比较低的Android系统中,也就是有更多的手机可以运行你的App。
5.1.3 四大组件
Activity被称作Android系统中的四大组件之一。这四大组件分别是Activity、BroardcastReceiver(广播接收者)、Service(服务)和ContentProvider(内容提供者)。
这四大组件后面都会介绍,现在你只需要记住,四大组件有个明显的特征:就是不能通过new直接实例化,而必须由Android系统创建它们。但前提是能让系统找到这四大组件的类定义。如果你自定义一个四大组件的类,必须在你的App的Manifest(名单)文件中声明它,这样系统才能找到这个类,才能实例化它。看一下我们的AndriodzManifest文件的内容,如图5.1.3.1所示。
图5.1.3.1
被红框框起来的就是我们App中当前唯一的Activity的声明。属性“android:name”的值“.MainActivity”是Activity的类名,此处省略了包名,但是前面的“.”不能省。其实有了这个类名,系统就可以通过反射的方式把Activity创建出来了。至于“<intent-filter>”元素的作用,后面会讲到。
如果你只创建了Activity的类,而没有在Manifest文件中声明它,那你的Activity是不能启动的。