• 001 Android开发初体验


    1、简介

    注:本文代码参考
    我们将开发本系列第一个应用,并借此学习一些Android基本概念以及构成应用的UI组件。
    初学习,如果没能全部理解,也不必担心,后续还会涉及这些内容并有更加详细的讲解。

    马上要开发的应用名叫GeoQuiz,它能给出一道道地理知识问题。用户点击TRUE或FALSE
    按钮来回答屏幕上的问题,GeoQuiz即时作出反馈。

    下图显示了用户点击TRUE按钮的结果:
    用户点击TRUE按钮图,图1

    1.1、Activity和布局文件

    GeoQuiz应用由一个activity和一个布局(layout)组成。

    • activity是Android SDK中 Activity类的一个实例,负责管理用户与应用界面的交互。
    • 应用的功能是通过编写 Activity 子类来实现的。对于简单的应用来说,一个 Activity 子
      类可能就够了,而复杂的应用则会有多个。 GeoQuiz是个简单应用,因此它只有一个名叫 QuizActivity 的 Activity
      子类。 QuizActivity它所对应的 用户界面。
    • 布局定义了一系列用户界面对象以及它们显示在屏幕上的位置。组成布局的定义保存在
      XML文件中。每个定义用来创建屏幕上的一个对象,如按钮或文本信息。

    GeoQuiz应用包含一个名叫activity_quiz.xml的布局文件。该布局文件中的XML标签定义了
    具体的用户界面。

    QuizActivity 与activity_quiz.xml文件的关系如下图2所示:
    Activity java文件与布局xml文件对应关系图:

    1.2、用户界面设计

    Android Studio如何创建项目以及Android Studio的界面介绍这里不赘述,我们通过Android Studio(以后简称“AS”)创建好GeoQuiz应用后,首先打开app/res/layout/activity_quiz.xml文件。如果看到的是布局预览界面,请点击底部的
    Text页切换显示XML代码。

    当前,activity_quiz.xml文件定义了默认的activity布局。

    应用activity的默认布局定义了两个组件(widget)RelativeLayout 和 TextView
    组件是用户界面的构造模块。组件可以显示文字或图像,与用户交互,甚至布置屏幕上的其
    他组件。按钮、文本输入控件和选择框等都是组件。
    Android SDK内置了多种组件,通过配置各种组件可获得所需的用户界面及行为。每一个组
    件都是 View 类或其子类(如 TextView 或 Button )的一个具体实例

    RelativeLayout 和 TextView 是在屏幕上的显示图 图3:
    mark

    QuizActivity 的用户界面需要下列组件:

    • 一个垂直 LinearLayout 组件;
    • 一个 TextView 组件;
    • 一个水平 LinearLayout 组件;
    • 两个 Button组件。

    组件是如何构成 QuizActivity 用户界面图 图4:
    mark

    下面我们在activity_quiz.xml文件中定义这些组件。

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="24dp"
            android:text="@string/question_text" />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
            <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/true_button" />
            <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/false_button" />
        </LinearLayout>
    </LinearLayout>
    

    上述代码暂时不理解也没关系,后续学习中逐渐弄明白的。
    注意,开发工具无法校验布局XML内容,拼写错误早晚会出问题,应尽量避免。

    可以看到,有三行以 android:text 开头的代码出现了错误信息。暂时忽略它们,稍后会
    处理。
    对照上图用户界面查看XML文件,可以看出组件与XML元素一一对应。元素的名
    称就是组件的类型

    各元素均有一组XML属性。属性可以看作如何配置组件的指令。
    为方便理解元素与属性的工作原理,接下来我们将以层级视角来研究布局。

    1.2.1、视图层级结构

    组件包含在视图(View)对象的层级结构中,这种结构又称作视图层级结构(view hierarchy)

    上述代码所示的XML布局对应的视图层级结构图 图5:

    从布局的视图层级结构可以看到,其根元素是一个 LinearLayout 组件。作为根元素,
    LinearLayout 组件必须指定Android XML资源文件的命名空间属性,这里是http://schemas.
    android.com/apk/res/android。

    LinearLayout 组件继承自 ViewGroup 组件(也是个 View 子类)。 ViewGroup 组件是包含并配
    置其他组件的特殊组件
    。想要以一列或一排的样式布置组件,就可以使用 LinearLayout 组件。
    其他 ViewGroup 子类还有 FrameLayout 、 TableLayout 和 RelativeLayout 。

    若某个组件包含在一个 ViewGroup 中,该组件与 ViewGroup 即构成父子关系。根 Linear-
    Layout 有两个子组件: TextView 和另一个 LinearLayout 。作为子组件的 LinearLayout 自己还
    有两个 Button 子组件。

    1.2.2、组件属性

    看看配置组件时常用的一些属性。

    1. android:layout_width 和 android:layout_height 属性
      几乎每类组件都需要 android:layout_width 和 android:layout_height 属性。以下是它
      们的两个常见属性值(二选一)。
      match_parent :视图与其父视图大小相同。
      wrap_content :视图将根据其显示内容自动调整大小。
      (以前还有个 fill_parent 属性值,等同于 match_parent ,现已废弃不用。)
      根 LinearLayout 组件的高度与宽度属性值均为 match_parent 。 LinearLayout 虽然是根元
      素,但它也有父视图——Android提供该父视图来容纳应用的整个视图层级结构。
      其他包含在界面布局中的组件,其高度与宽度属性值均被设置为 wrap_content 。

    TextView 组件比其包含的文字内容区域稍大一些,这主要是 android:padding="24dp" 属性
    的作用。该属性告诉组件在决定大小时,除内容本身外,还需增加额外指定量的空间。这样屏幕
    上显示的问题与按钮之间便会留有一定的空间,使整体显得更为美观。(不理解dp的意思?dp即
    density-independent pixel,指与密度无关的像素。)
    2. android:orientation 属性
    android:orientation 属性是两个 LinearLayout 组件都具有的属性,它决定两者的子组件
    是水平放置还是垂直放置。根 LinearLayout 是垂直的,子 LinearLayout 是水平的。

    子组件的定义顺序决定其在屏幕上显示的顺序。在垂直的 LinearLayout 中,第一个定义的
    子组件出现在屏幕的最上端;而在水平的 LinearLayout 中,第一个定义的子组件出现在屏幕的
    最左端。(如果设备文字从右至左显示,如阿拉伯语或者希伯来语,第一个定义的子组件则出现
    在屏幕的最右端。)
    3. android:text 属性
    TextView 与 Button 组件具有 android:text 属性。该属性指定组件要显示的文字内容。
    请注意, android:text 属性值不是字符串值,而是对字符串资源(string resource)的引用。

    字符串资源包含在一个独立的名叫strings的XML文件中(strings.xml),虽然可以硬编码设置
    组件的文本属性值,如 android:text="True" ,但这通常不是个好主意。

    比较好的做法是:将文
    字内容放置在独立的字符串资源XML文件中,然后引用它们。这样会方便应用的本地化(支持
    多国语言)。
    需要在activity_quiz.xml文件中引用的字符串资源还没添加。现在就来处理。

    1.2.3、创建字符串资源

    每个项目都包含一个默认字符串资源文件strings.xml。

    在项目工具窗口中,找到app/res/values目录,展开目录,打开strings.xml文件。
    可以看到,项目模板已经添加了一些字符串资源。如下代码所示,添加应用布局需要
    的三个新的字符串。

    <resources>
        <string name="app_name">GeoQuiz</string>
        <string name="question_text">Canberra is the capital of Australia.</string>
        <string name="true_button">True</string>
        <string name="false_button">False</string>
    </resources>
    

    (某些版本的Android Studio的strings.xml默认带有其他字符串,请勿删除它们,否则会引发与
    其他文件的联动错误。)

    现在,在GeoQuiz项目的任何XML文件中,只要引用到 @string/false_button ,应用运行
    时,就会得到文本“False”。

    保存strings.xml文件。这时,activity_quiz.xml布局缺少字符串资源的提示信息应该就消失了。
    (如仍有错误提示,请检查一下这两个文件,确认没有拼写错误。)

    默认的字符串文件虽然已命名为strings.xml,仍可以按个人喜好重命名。一个项目也可以
    有多个字符串文件。只要这些文件都放在res/values/目录下,含有一个 resources 根元素,以及多
    个 string 子元素,应用就能找到并正确使用它们。

    1.3、从布局 XML 到视图对象

    知道activity_quiz.xml中的XML元素是如何转换为视图对象的吗?答案就在于 QuizActivity
    类。

    在创建GeoQuiz项目的同时,向导也创建了一个名叫 QuizActivity 的 Activity 子类。
    QuizActivity 类文件存放在项目的app/java目录下。java目录是项目全部Java源代码的存放处。

    在项目工具窗口中,依次展开app/java目录与com.bignerdranch.android.geoquiz包。找到并打
    开QuizActivity.java文件,查看其中的代码,如下所示:

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    public class QuizActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_quiz);
        }
    }
    

    是不是不明白 AppCompatActivity 的作用?它实际就是一个 Activity 子类,能为Android
    旧版本系统提供兼容支持。

    如果无法看到全部类包导入语句,请单击第一行导入语句左边的⊕符号来显示它们。

    该Java类文件有一个 Activity 方法: onCreate(Bundle) 。
    (如果你的文件还包含 onCreateOptionsMenu(Menu) 和 onOptionsItemSelected(MenuItem)
    方法,暂时不用理会)
    activity子类的实例创建后, onCreate(Bundle) 方法会被调用。activity创建后,它需要获取
    并管理用户界面。要获取activity的用户界面,可调用以下 Activity 方法:

    public void setContentView(int layoutResID)

    根据传入的布局资源ID参数,该方法生成指定布局的视图并将其放置在屏幕上。布局视图生
    成后,布局文件包含的组件也随之以各自的属性定义完成实例化。

    1.3.1、资源与资源 ID

    布局是一种资源。资源是应用非代码形式的内容,如图像文件、音频文件以及XML文件等。

    项目的所有资源文件都存放在目录app/res的子目录下。在项目工具窗口中可以看到,
    activity_quiz.xml布局资源文件存放在res/layout/目录下。strings.xml字符串资源文件存放在
    res/values/目录下。

    可以使用资源ID在代码中获取相应的资源。activity_quiz.xml布局的资源ID为R.layout.
    activity_quiz。

    查看GeoQuiz应用的资源ID需要切换项目视图。Android Studio默认使用Android项目视图,
    图6所示。为让开发者专注于最常用的文件和目录,默认视图隐藏了Android项目的真实文件
    目录结构。

    图6:
    mark

    在项目工具窗口的最上部找到下拉菜单,从Android项目视图切换至Project视图。Project视图
    会显示出当前项目的所有文件和目录。

    展开目录app/build/generated/source/r/debug,找到项目包名称并打开其中的R.java文件,即可
    看到GeoQuiz应用当前所有的资源。R.java文件在Android项目编译过程中自动生成,如该文件头
    部的警示所述,请不要修改该文件的内容。

    修改布局或字符串等资源后,R.java文件不会实时刷新。Android Studio另外还存有一份代码
    编译用的R.java隐藏文件。当前代码编辑区打开的R.java文件仅在应用安装至设备或模拟器前产
    生,因此只有在Android Studio中点击运行应用时,它才会得到更新。
    R.java文件通常比较大,如下所示:

    /* AUTO-GENERATED FILE. DO NOT MODIFY.
    *
    * This class was automatically generated by the
    * aapt tool from the resource data it found. It
    * should not be modified by hand.
    */
    
    public final class R {
    public static final class anim {
    ...
    }
    ...
    public static final class id {
    ...
    }
    public static final class layout {
        ...
        public static final int activity_quiz=0x7f030017;
        }
        public static final class mipmap {
        public static final int ic_launcher=0x7f030000;
    }
    public static final class string {
    ...
        public static final int app_name=0x7f0a0010;
            public static final int false_button=0x7f0a0012;
            public static final int question_text=0x7f0a0014;
            public static final int true_button=0x7f0a0015;
        }
    }
    

    可以看到R.layout.activity_quiz即来自该文件。 activity_quiz 是 R 的内部类 layout 里的一个
    整型常量名。

    GeoQuiz应用需要的字符串同样具有资源ID。目前为止,我们还未在代码中引用过字符串,
    如果需要,可以使用以下方法:
    setTitle(R.string.app_name);

    Android为整个布局文件以及各个字符串生成资源ID,但activity_quiz.xml布局文件中的组件
    除外,因为不是所有组件都需要资源ID。在本章中,我们要在代码里与两个按钮交互,因此只需
    为它们生成资源ID即可。

    这里主要使用Android项目视图,生成资源ID之前,记得切回。当然,如果你就喜欢使用Project
    视图,也没啥问题。

    要为组件生成资源ID,请在定义组件时为其添加 android:id 属性。在activity_quiz.xml文件
    中,分别为两个按钮添加上 android:id 属性,如下代码所示:

    <LinearLayout ... >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="24dp"
            android:text="@string/question_text" />
            
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            
            <Button
                android:id="@+id/true_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/true_button" />
            
            <Button
                android:id="@+id/false_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/false_button" />
                
        </LinearLayout>
        
    </LinearLayout>
    

    注意, android:id 属性值前面有一个+标志,而 android:text 属性值则没有。这是因为我
    们在创建资源ID,而对字符串资源只是做引用

    1.4、组件的实际应用

    按钮有了资源ID,就可以在 QuizActivity 中直接获取它们。首先,在QuizActivity.java文件
    中增加两个成员变量。

    在QuizActivity.java文件中输入代码:

    public class QuizActivity extends AppCompatActivity {
        private Button mTrueButton;
        private Button mFalseButton;
        @Override
        
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_quiz);
        }
    }
    

    文件保存后,会看到两个错误提示。没关系,稍后会处理。请注意新增的两个成员(实例)
    变量名称的 m 前缀。该前缀是Android编程应遵循的命名约定

    现在,将鼠标移至代码左边的错误提示处时,会看到两条同样的错误信息:Cannot resolve
    symbol 'Button'。

    这告诉我们,需要在QuizActivity.java文件中导入 android.widget.Button 类包。可在文件
    头部手动输入以下代码:
    import android.widget.Button;

    或者使用Option+Return(Alt+Enter)组合键,让Android Studio自动为你导入。代码有误时,
    也可以使用该组合键来修正。记得要常用。

    类包导入后,刚才的错误提示应该就消失了。(如果仍然存在,请检查Java代码以及XML文
    件,确认是否存在输入或拼写错误。)
    接下来,我们来编码使用按钮组件,这需要以下两个步骤:

    • 引用生成的视图对象;
    • 为对象设置监听器,以响应用户操作。

    1.4.1 引用组件

    在activity中,可调用以下 Activity 方法引用已生成的组件:
    public View findViewById(int id)

    该方法以组件的资源ID作为参数,返回一个视图对象。
    在QuizActivity.java文件中,使用按钮的资源ID获取视图对象,赋值给对应的成员变量。注意,赋值前,必须先将返回的 View 类型转换为 Button 。

    public class QuizActivity extends AppCompatActivity {
        private Button mTrueButton;
        private Button mFalseButton;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_quiz);
            mTrueButton = (Button) findViewById(R.id.true_button);
            mFalseButton = (Button) findViewById(R.id.false_button);
        }
    }
    

    1.4.2 设置监听器

    Android应用属于典型的事件驱动类型。不像命令行或脚本程序,事件驱动型应用启动后,
    即开始等待行为事件的发生,如用户点击某个按钮。(事件也可以由操作系统或其他应用触发,
    但用户触发的事件更直观,如点击按钮。)

    应用等待某个特定事件的发生,也可以说应用正在“监听”特定事件。为响应某个事件而创
    建的对象叫作监听器(listener)。监听器会实现特定事件的监听器接口(listener interface)。

    无需自己动手,Android SDK已经为各种事件内置了很多监听器接口。当前应用需要监听用
    户的按钮“点击”事件,因此监听器需实现 View.OnClickListener 接口。

    首先处理TRUE按钮。在QuizActivity.java文件中,在 onCreate(Bundle) 方法的变量赋值语
    句后输入下列代码

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
        mTrueButton = (Button) findViewById(R.id.true_button);
        mTrueButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Does nothing yet, but soon!
            }
        });
        mFalseButton = (Button) findViewById(R.id.false_button);
    }
    

    (如果遇到View cannot be resolved to a type的错误提示,请使用Option+Return(Alt+Enter)快
    捷键导入 View 类。)

    在上面代码中,我们设置了一个监听器。按钮 mTrueButton 被点击后,监听器会立即通
    知我们。传入 setOnClickListener(OnClickListener) 方法的参数是一个监听器。它是一个实
    现了 OnClickListener 接口的对象。

    使用匿名内部类
    这里,一个匿名内部类(anonymous inner class)实现了 OnClickListener 接口。语法看上去
    稍显复杂,不过有个助记小技巧最外层一对括号内的全部代码就是传入 setOnClickListener
    (OnClickListener) 方法的参数

    mTrueButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Does nothing yet, but soon!
        }
    });
    

    后续所有的监听器都以匿名内部类来实现。这样做有两大好处:

    • 第一,使用匿名内部类,可 以相对集中地实现监听器方法,一眼可见;
    • 第二,事件监听器一般只在一个地方使用,使用匿名
      内部类,就不用去创建繁琐的命名类了。

    匿名内部类实现了 OnClickListener 接口,因此它也必须实现该接口唯一的 onClick(View)
    方法。 onClick(View) 现在是个空方法。虽然必须实现 onClick(View) 方法,但具体如何实现取
    决于使用者,因此即使是个空方法,编译器也可以编译通过。
    (如果匿名内部类、监听器、接口等概念已忘得差不多了,现在就该去复习一下,或找本参
    考手册备查。)

    1.5、创建提示消息

    接下来要实现的是,分别点击两个按钮,弹出我们称之为toast的提示消息。Android的toast
    是用来通知用户的简短弹出消息,用户无需输入什么,也不用做任何干预操作。这里,我们要用
    toast来反馈答案,如图7所示:
    mark

    首先回到strings.xml文件,如下代码所示,为toast添加消息显示用的字符串资源。

    <resources>
        <string name="app_name">GeoQuiz</string>
        <string name="question_text">Canberra is the capital of Australia.</string>
        <string name="true_button">True</string>
        <string name="false_button">False</string>
        <string name="correct_toast">Correct!</string>
        <string name="incorrect_toast">Incorrect!</string>
    </resources>
    

    调用 Toast 类的以下方法,可创建toast:
    public static Toast makeText(Context context, int resId, int duration)

    该方法的 Context 参数通常是 Activity 的一个实例( Activity 本身就是 Context 的子类)。
    第二个参数是toast要显示字符串消息的资源ID。 Toast 类必须借助 Context 才能找到并使用字符
    串资源ID。第三个参数通常是两个 Toast 常量中的一个,用来指定toast消息的停留时间。

    创建toast后,可调用 Toast.show() 方法在屏幕上显示toast消息。
    在 QuizActivity 代码里,分别调用 makeText(...) 方法。在添加
    makeText(...) 时,可利用Android Studio的代码自动补全功能,让代码输入更轻松。

    使用代码自动补全
    代码自动补全功能可以节约大量开发时间,越早掌握受益越多。

    依次输入下面代码。当输入到 Toast 类后的点号时,Android Studio会弹出一
    个窗口,窗口内显示了建议使用的 Toast 类的常量与方法。

    要选择需要的建议方法,使用上下键。(如果不想使用代码自动补全功能,请不要按Tab键、
    Return/Enter键,或使用鼠标点击弹出窗口,只管继续输入代码直至完成。)

    在建议列表里,选择 makeText(Context context, int resID, int duration) 方法,代
    码自动补全功能会自动添加完整的方法调用。
    完成 makeText 方法的全部参数设置,完成后的代码如下代码所示:

    mTrueButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(QuizActivity.this,
            R.string.correct_toast,
            Toast.LENGTH_SHORT).show();
            // Does nothing yet, but soon!
        }
    });
    mFalseButton = (Button) find ViewById(R.id.false_button);
    mFalseButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(QuizActivity.this,
            R.string.incorrect_toast,Toast.LENGTH_SHORT).show();
        }
    });
    

    在 makeText(...) 里,传入 QuizActivity 实例作为 Context 的参数值。注意此处应输入的
    参数是 QuizActivity.this ,不要想当然地直接输入 this 。因为匿名类的使用,这里的 this 指
    的是监听器 View.OnClickListener 。

    使用代码自动补全功能,自己也就不用导入 Toast 类了,因为Android Studio会自动导入相
    关类。

    好了,现在可以运行应用了。

    1.6、 使用模拟器运行应用

    运行Android应用需使用硬件设备或虚拟设备(virtual device)。包含在开发工具中的Android
    设备模拟器可提供多种虚拟设备。

    要创建Android虚拟设备(AVD),在Android Studio中,选择Tools → Android → AVD Manager
    菜单项。AVD管理器窗口弹出时,点击窗口左下角的+Create Virtual Device…按钮。一路next,详细的创建不赘述了。

    创建完成后即可启动运行。

    AVD创建成功后,我们用它运行GeoQuiz应用。点击Android Studio工具栏上的Run按钮,或
    者使用Control+R快捷键。Android Studio会自动找到新建的虚拟设备,安装应用包(APK),然后
    启动并运行应用。
    模拟器的启动过程比较耗时,请耐心等待。等设备启动完成,应用运行后,就可以在应用界
    面点击按钮,让toast告诉你答案了。
    假如启动时或在点击按钮时,GeoQuiz应用崩溃,可以在Android DDMS工具窗口的LogCat
    视图中看到有用的诊断信息。(如果LogCat没有自动打开,可点击Android Studio窗口底部的
    Android Monitor按钮打开它。),查看日志。

    最好不要关掉模拟器,这样就不必在反复运行调试应用时,浪费时间等待AVD启动了。
    单击AVD模拟器上的后退按钮可以停止应用。这个后退按钮的形状像一个指向左侧的三角形
    (在较早版本的Android中,它像一个U型箭头)。需要调试变更时,再通过Android Studio重新运
    行应用。

    模拟器虽然好用,但在实体设备上测试应用能获得更准确的结果。

    1.7、深入学习:Android 编译过程

    学习到这里,你可能迫切想知道Android是如何编译的。
    你已经知道在项目文件发生变化时,
    Android Studio无需指示便会自动进行编译。

    在整个编译过程中,Android开发工具将资源文件、
    代码以及AndroidManifest.xml文件(包含应用的元数据)编译生成.apk文件。.apk文件要在模拟器上
    运行,还需以debug key签名。(分发.apk应用给用户时,应用必须以release key签名。更多有关编译
    过程的信息,可参考Android开发文档网页developer.android.com/tools/publishing/preparing.html。)

    那么,应用的activity_quiz.xml布局文件的内容该如何转变为 View 对象呢?作为编译过程的
    一部分,aapt(Android Asset Packaging Tool)将布局文件资源编译压缩紧凑后,打包到.apk文件
    中。

    然后,在 QuizActivity 类的 onCreate(Bundle) 方法调用 setContentView(...) 方法时,
    QuizActivity 使用 LayoutInflater 类实例化布局文件中定义的每一个 View 对象,如图8所示:
    mark

    1.7.1、Android 编译工具

    当前,我们看到的项目编译都是在Android Studio里执行的。编译功能已整合到IDE中,IDE
    负责调用aapt等Android标准编译工具,但编译过程本身仍由Android Studio管理。

    有时,出于某种原因,可能需要脱离Android Studio编译代码。最简单的方法是使用命令行
    编译
    工具。现代Android编译系统使用Gradle编译工具

    要从命令行使用Gradle,请切换到项目目录并执行以下命令:
    $ ./gradlew tasks

    如果是Windows系统,执行以下命令:

    gradlew.bat tasks

    执行以上命令会显示一系列可用任务。你需要的任务是installDebug,因此,再执行以下命令:
    $ ./gradlew installDebug
    如果是Windows系统,执行以下命令:

    gradlew.bat installDebug

    以上命令将把应用安装到当前连接的设备上,但不会运行它。要运行应用,需要在设备上手
    动启动。

  • 相关阅读:
    LeetCode数据库178
    LeetCode数据库181
    LeetCode数据库177
    LeetCode数据库176
    HNOI2003 消防局的设立
    HNOI2001 产品加工
    Luogu P1020 关路灯
    NOIP2004 虫食算
    SP2713 GSS4-Can you answer these queries IV
    APIO2008 免费道路
  • 原文地址:https://www.cnblogs.com/xlfcjx/p/16367204.html
Copyright © 2020-2023  润新知