1.4 App的工程结构

上一节我们在模拟器上成功地运行了第一个App(HelloWolrd),接下来好好研究一下它的工程结构。每个App的工程结构都差不多,只要掌握了基本结构,后面开发起来就会得心应手。

1.4.1 工程目录说明

AndroidStudio的工程创建分两个层级:第一个层级通过菜单File→New→NewProject创建,这里的新项目是指新的工作空间,对应Eclipse的workspace;第二个层级通过菜单File→New→NewModule创建,这里的新模块是指一个单独的App工程,对应Eclipse的project。第一次运行AndroidStudio都是选择NewProject,表示先创建一个工作空间;后面还想创建新的App工程时,只需选择NewModule,表示在当前工作空间下新建一个App工程。

例如,图1-27是之前HelloWorld工程的目录结构图。

图1-27 HelloWorld工程的目录结构图

从结构图中可以看到,该工程下面有两个目录:一个是app,另一个是Gradle Scripts。其中,app下面又有3个子目录,功能说明如下:

(1)manifests子目录,下面只有一个xml文件,即AndroidManifest.xml,是App的运行配置文件。

(2)java子目录,下面有3个com.example.hellorworld包,其中第一个包存放的是App工程的java源代码,后面两个包存放的是测试用的java代码。

(3)res子目录,存放的是App工程的资源文件。res子目录下又有4个子目录:

● drawable目录存放的是图形描述文件与用户图片。

● layout目录存放的是App页面的布局文件。

● mipmap目录存放的是启动图标。

●values目录存放的是一些常量定义文件,比如字符串常量strings.xml、像素常量dimens.xml、颜色常量colors.xml、样式风格定义styles.xml等。

Gradle Scripts下面主要是工程的编译配置文件,主要有:

(1)build.gradle,该文件分为项目级与模块级两种,用于描述App工程的编译规则。

(2)proguard-rules.pro,该文件用于描述java文件的代码混淆规则。

(3)gradle.properties,该文件用于配置编译工程的命令行参数,一般无须改动。

(4)settings.gradle,配置哪些模块在一起编译。初始内容为include ':app',表示只编译App模块。

(5)local.properties,项目的本地配置,一般无须改动。该文件是在工程编译时自动生成的,用于描述开发者本机的环境配置,比如SDK的本地路径、NDK的本地路径等。

1.4.2 编译配置文件build.gradle

项目级别的build.gradle一般无须改动,我们只需关注模块级别的build.gradle。下面在初始的build.gradle文件中补充文字注释,方便读者更好地理解每个参数的用途。

        apply plugin:'com.android.application'


        android {
            // 指定编译用的SDK版本号,如25表示使用Android 7.1编译
            compileSdkVersion 25
            // 指定编译工具的版本号。这里的头两位数字必须与compileSdkVersion保持一致,具体的版本号
    可在sdk安装目录的sdk\build-tools下找到
            buildToolsVersion "25.0.2"


            defaultConfig {
              // 指定该模块的应用编号,即App的包名。该参数为自动生成,无须修改
              applicationId "com.example.helloworld"
              // 指定App适合运行的最小SDK版本号,如15表示至少要在Android 4.0.3上运行
              minSdkVersion 15
              // 指定目标设备的SDK版本号,即该App最希望在哪个版本的Android上运行
              targetSdkVersion 25
              // 指定App的应用版本号
              versionCode 1
              // 指定App的应用版本名称
              versionName "1.0"
            }
            buildTypes {
              release {
                  // 指定是否开启代码混淆功能。true表示开启混淆,false表示无须混淆。
                  minifyEnabled false
                  // 指定代码混淆规则文件的文件名
                  proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
              }
            }
        }


        // 指定App编译的依赖信息
        dependencies {
            // 指定引用jar包的路径
            compile fileTree(dir:'libs', include:['*.jar'])
            // 指定单元测试编译用的junit版本号
            testCompile 'junit:junit:4.12'
            // 指定编译Android的高版本支持库,如AppCompatActivity必须指定编译appcompat-v7库
            compile 'com.android.support:appcompat-v7:25.1.0'
        }

1.4.3 App运行配置AndroidManifest.xml

AndroidManifest.xml用于指定App内部的运行配置,是一个XML描述文件,根节点为manifest,根节点的package指定了该App的包名。manifest下面又有若干子节点,分别说明如下:

(1)uses-sdk,该节点有两个属性:android:minSdkVersion和android:targetSdkVersion。这两个属性是早期Eclipse开发App时使用的,现在这两个字段改成放到build.gradle文件中,故而Android Studio不配置uses-sdk也没有关系。

(2)uses-permission,该节点用于声明App运行过程中需要的权限名称。例如,访问网络需要上网权限,拍照需要摄像头权限,定位需要定位权限等。

(3)application,该节点用于指定App的自身属性,默认的属性说明如下:

● android:allowBackup,用于指定是否允许备份,开发阶段设置为true,上线时设置为false。

● android:icon,用于指定该App在手机屏幕上显示的图标。

● android:label,用于指定该App在手机屏幕上显示的名称。

● android:supportsRtl,设置为true表示支持阿拉伯语/波斯语这种从右往左的文字排列顺序。

● android:theme,用于指定该App的显示风格。

application节点下还有几个子节点,比如活动activity、服务service、广播接收器receiver、内容提供器provider等,这些子节点的详细属性会在后续章节详细说明。

1.4.4 在代码中操纵控件

在一开始创建Hello World工程时,Android Studio默认打开了两个文件,分别是布局文件activity.xml和代码文件MainActivity.java。下面先看布局文件activity.xml的内容:

        <? xml version="1.0" encoding="utf-8"? >
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            tools:context="com.example.helloworld.MainActivity">


            <TextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello World! " />
        </RelativeLayout>

这里可以看到xml文件中只有两个节点,分别是RelativeLayout和TextView。再仔细看看,有没有发现我们熟悉的Hello World?没错,模拟器App界面显示的Hello World就来自于这里,也就是TextView控件的android:text属性值。可以把这里的Hello World改为其他文字,比如“你好、世界”或I Love Android,改完保存文件后再依次选择菜单Run→Run 'app',看看App界面上的文字是不是变成新的了?

当然,我们的目标并不仅限于在布局文件中修改文字,还要能够在代码中修改文字的内容。再次打开代码文件MainActivity.java,看看里面有什么内容。该java文件中MainActivity类的内容如下:

        public class MainActivity extends AppCompatActivity {


            @Override
            protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
            }
        }

这里可以看出,MainActivity.java的代码内容很简单,只有一个MainActivity类,该类下面只有一个函数onCreate。注意onCreate内部的setContentView方法直接引用了布局文件的名字activity_main,该方法的意思是往App界面填充activity.xml的布局内容。现在我们要在这里改动改动,加点“绿叶红花”让它好看一些。首先打开activity.xml,在TextView节点下方补充一行android:id="@+id/tv_hello";然后回到MainActivity.java,在setContentView方法下面补充如下几行代码:

              //获取名字为tv_hello的TextView控件
              TextView tv_hello = (TextView) findViewById(R.id.tv_hello);
              //给TextView控件设置文字内容
              tv_hello.setText("今天天气真热啊,火辣辣的");
              //给TextView控件设置文字颜色
              tv_hello.setTextColor(Color.RED);
              //给TextView控件设置文字大小
              tv_hello.setTextSize(30);

保存文件后依次选择菜单Run→Run 'app',模拟器上的App界面就变成了如图1-28所示的样子。

图1-28 修改文字后的HelloWorld界面

现在不但文字内容改变了,文字颜色和字体大小也发生了变化。怎么样,是不是很有成就感呢?好的开始是成功的一半,现在我们初步学会了在代码中操作控件,下一章进一步学习在App界面上人机交互。