Android关于活动Activity的教程

本文介绍了Android开发中Activity的基本概念及使用方法,包括创建、加载布局、设置点击事件及使用Intent进行Activity间跳转等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关引用:

《第一行代码 第2版》

https://developer.android.com/guide/topics/ui/notifiers/toasts.html

从上节我们可以知道,Android包含四大组件:

  • Activity
  • BroadCastReceiver
  • Service
  • ContentProvider

作为一个嵌入式设备的程序,对于用户来说,最直观的就是界面显示了,所以本篇课程学学Activity的知识

什么是活动(Activity)

JavaSE中,程序的入口是main()函数;而在Android中,若这个程序是被用户可见的,则需用用到Android的组件————Activity,它是一个可以包含用户界面的组件,被用户交互操作。

一个Android程序包含零到多个Activity。

基本用法

怎么创建

若你创建一个Android项目的时候,不更改默认配置,IDE会自动帮你生成带Activity组件的项目(至于如何创建,可自行google)。下面我们准备手动创建一个Activity,选择Add No Activity:
手动创建一个Activity
我学Android的时候,流行的IDE还是Eclipse,所以我习惯了它的窗口界面,在开发中,我一般都是将Android Studio改成Project模式:
Project模式
鼠标右击包名 → New → Activity → Empty Activity,会弹出下图的对话框,不要勾选Generate Layout File和Launcher Activity:
创建一个Activity
打开FirstActivity.java,由于继承了Actvity(AppCompatActivity是Activity的子类),所以Android Studio自动帮我们重写了onCreate()方法:

    public class FirstActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    }

在Android中,只要看到onXxx()的方法,其实就是理解为 在xxx时候执行,例如onCreate()几时在创建的时候执行,onClick()在组件被点击的时候执行,onDestory()在销毁的时候执行……

加载内容布局

前面说到,创建Activity时不够选Generate Layout File是为了我们自己手动创建布局文件,那什么是布局文件呢???其实布局文件就是用来显示界面内容的

如何创建

从上节我们知道,Android的布局文件是放在layout目录的,创建目录:
创建layout目录

接下来就可以在这个目录下创建我们的布局文件了,并命名为firstactivity_layout:
创建布局文件1

创建布局文件2

创建完成后,Android Studio会自动显示可视化布局编辑器窗口:
可视化编辑器窗口

图片左下角有两个切换卡,左边是Design,右边是Text。前者是可视化布局编辑器,在这里你不仅可以预览当前的布局,还可以通过拖放的方式编辑布局;而Text则是通过XML文件的方式来编辑布局的,一般情况下是用XML方式编辑布局,所以我们切换到Text:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

</LinearLayout>

在这里我们可以添加一个最简单的组件:Button(按钮):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="按钮"/>

</LinearLayout>
xml中各元素属性的含义

这里对Button的几个属性进行讲解:

  1. android:id是Button这个组件的唯一标识,类似于现实生活中人们的身份证,如果要在java代码中操作某个组件,则组件需要设置id,这样才能在代码中通过id拿到这个组件。注意:定义一个id格式是@+id/xxxxx,不能写成@id/xxxxxx,后者表示引用一个资源
  2. android:layout_width和android:layout_height,顾名思义,表示组件的宽度和高度,match_parent表示和父元素一样宽,而Button的父元素是LinearLayout,LinearLayout的宽度也为match_parent,那是多少呢??这里你可以简单先理解成和屏幕一样宽,本系列只讲基础知识;wrap_content则表示高度刚好包含Button里面的内容
  3. android:text指定了Button显示的内容。

我们可以点击右侧工具栏的Preview预览一下效果:
Preview预览视图

显示布局

布局文件的创建工作已经完成了,现在让我们在Activity中加载它,显示出来吧:

public class FirstActivity extends AppCompatActivity {

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

上述代码中,是使用setContentView()给当前Activity加载布局的,使用方法是往这个方法传入一个int型的布局文件id。上节中提过,项目中的资源文件都会在R文件中生成一个唯一标识的资源id。因此我们把创建的布局文件id传入即可。

在清单文件中注册(AS自动完成)

上一章说过,Android的四大组件必须在清单文件中注册才能生效,activity自然不例外,只是Android Studio贴心的帮我们完成了这个动作:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.snaptech.activitytest">

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".FirstActivity"></activity>
</application>

</manifest>

清单文件元素属性的含义

  1. 标签中android:name是来指定具体注册哪个活动的,这里填入的.FirstAcitivity是什么意思呢?其实这不过就是com.snaptech.activitytest.FirstActivity的缩写而已。由于在最外层的标签中已经通过package属性指定了程序的包名是com.snaptech.activitytest,因此在注册活动时这一部分就可以省略了,直接使用.FirstActivity就足够了。

设置活动为主入口

上一章中说过,Activity要想作为主入口,只需要如下声明即可:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.snaptech.activitytest">

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".FirstActivity"
    android:label="This is FirstActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

</manifest>

android:label是用来指定活动中标题栏内容的,标题栏是显示在活动最顶部的。label不仅会成为标题栏中的内容,还会成为Launcher中应用程序显示的名称。运行本程序,结果如下:
运行效果图

使用onClick()+Toast打印

对于什么是Toast,Android官网的定义是:

A toast provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current activity remains visible and interactive. Toasts automatically disappear after a timeout.

简单翻译就是,Toast框是一个小的弹出窗口,用于提供有关操作的简单反馈。它只填充消息所需的空间大小,并且当前的Activity仍然是保持可见并且可以和用户交互的(此处涉及到Activity的生命周期,下文会讲解)。Toast框会在设定的时间超时后,自动消失。

另外我们要知道,按钮是可点击的,我们可以通过给按钮Button设置点击监听事件来实现:

public class FirstActivity extends AppCompatActivity {

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

        //findViewById()通过在R文件的唯一标识id获取组件,返回的是View对象,而View对象是所有组件的父类,所以要向下转型为Button对象。
        Button button = (Button) findViewById(R.id.btn_button);
        //通过该方法为Button注册一个点击的监听器
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {//还记得上文所说的诀窍吗??onXxx()就是在Xxx的时候调用,此处Button为点击的时候调用
                //通过Toast的静态方法makeText()创建Toast对象,传入三个参数,第一个是上下文对象Context,直接传入Activity本身,第二个是要现实的内容,第三个是显示的时长,有两个常量选择Toast.LENGTH_SHORT和Toast.LENGTH_LONG。记得最后调用.show()方法,不然不会显示!!!
                Toast.makeText(FirstActivity.this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
            }
        });
    }
}

点击Button,结果:

onClick()+Toast

点击事件的四种写法

下面介绍组件点击事件的四种方法:

第一种

自定义一个类,并实现onClickListener接口:

public class FirstActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.btn_button);
        button.setOnClickListener(new ClickListener());
    }

    class ClickListener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            Toast.makeText(FirstActivity.this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
        }
    }
}

第二种

定义一个匿名内部类实现onClickListener接口

public class FirstActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.btn_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(FirstActivity.this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
            }
        });
    }
}

第三种

让当前activity实现onClickListener接口

public class FirstActivity extends AppCompatActivity implements View.OnClickListener{

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

        Button button = (Button) findViewById(R.id.btn_button);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Toast.makeText(FirstActivity.this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
    }
}

第四种

在xml文件中给Button节点设置onClick属性,然后在activity中定义跟该属性值同名的方法:

public class FirstActivity extends AppCompatActivity{

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

        Button button = (Button) findViewById(R.id.btn_button);
    }

    public void onButtonClick(View v){
        Toast.makeText(this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
    }
}

在Android官网中,对于此种方法是这样介绍的:

For instance, if you specify android:onClick=”sayHello”, you must declare a public void sayHello(View v) method of your context (typically, your Activity).

如果你在xml中设置了这个属性,那么你必须在你的上下文中声明一个public类型的方法,并且形参类型为View。

销毁一个活动

上面学习了如何创建一个活动,那么如果想要销毁一个活动呢?其实只要按一下Back键就可以了。如果你想在代码中实现,可以调用Activity类的finish()方法:

public class FirstActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.btn_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Toast.makeText(FirstActivity.this,"button is clicked !!! ",Toast.LENGTH_SHORT).show();
                FirstActivity.this.finish();
            }
        });
    }
}

运行效果和按下Back键是一样的

Intent

如果想要在两个Activity之间跳转的话,就要用到Intent,通过设置Intent对象的参数指定要跳转的Activity。

概念

Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务以及发送广播等场景。

显式Intent

通过设置Acitivity的包名和类名实现的跳转,称为显示意图

隐式Intent

通过指定一系列的action和category,交由系统去分析这个Intent然后做出响应,称为隐式意图

实践

我们可以利用Intent从FirstActivity跳转到SecondActivity。

创建第二个Activity

利用前面介绍的创建Activity的方法创建SecondActivity:

public class SecondActivity extends AppCompatActivity {

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

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button2"/>

</LinearLayout>

还是在SecondActivity的界面上简单的定义了一个Button,内容为Button2。
别忘了在清单文件中检查是否注册了这个Activity:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".FirstActivity"
        android:label="This is FirstActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".SecondActivity"></activity>
</application>

由于不是入口Activity,所以不需要配置FirstActivity里的内容。

显式意图跳转

要从FirstActivity显示跳转到SecondActivity:

public class FirstActivity extends AppCompatActivity{

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

        Button button = (Button) findViewById(R.id.btn_button);
    }

    public void onButtonClick(View view){
        Intent intent = new Intent(this,SecondActivity.class);
        startActivity(intent);
    }
}

点击FirstActivity中的“按钮”,程序会经过动画跳转到SecondActvity,并显示后者的布局内容:
显示Intent跳转

隐式意图跳转

还记得我们在清单文件中注册FirstActivity时候,所设置的属性吗?其实这些属性就是被用于其他Activity隐式启动的。

打开清单文件,为SecondActivity设置action和category:

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

action的android:name其实可以随便写,但是最好写规范。要想让一个Activity被隐式启动,必须设置action与category!
隐式意图启动Activity成功的条件:Intent参数的值必须与该Activity在清单文件中属性的定义的值同时匹配

public class FirstActivity extends AppCompatActivity{
    private final String INTENT_ACTION = "com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstactivity_layout);

        Button button = (Button) findViewById(R.id.btn_button);
    }

    public void onButtonClick(View view){
        Intent intent = new Intent(INTENT_ACTION);
        //实际上有调用以下代码,只不过是自动帮你添加了
        //intent.addCategory(Intent.CATEGORY_DEFAULT);
        startActivity(intent);
    }
}

等等,前面不是说必须要和同时匹配才能响应吗?怎么没看到指定category?其实这是因为android.intent.category.DEFAULT是一种默认的category,在调用startActivity()方法时,会自动将这个category添加到Intent中。运行程序,效果和显示意图启动一致。

我们再修改清单文件中SecondActivity的属性:

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY"/>
        <action android:name="com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY_TEMP"/>
        <category android:name="com.snaptech.activitytest.CATEGORY_SECOND_ACTIVITY"/>
    </intent-filter>
</activity>

这里设置了两个,在FirstActivity中将Intent的action指定为其中任何一个:

public class FirstActivity extends AppCompatActivity{
    private final String INTENT_ACTION = "com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY";
    private final String INTENT_ACTION_TEMP = "com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY_TEMP";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstactivity_layout);

        Button button = (Button) findViewById(R.id.btn_button);
    }

    public void onButtonClick(View view){
        Intent intent = new Intent(INTENT_ACTION_TEMP);
        startActivity(intent);
    }
}

重新运行程序,报错:

Tips:程序出现错误,将Tag过滤器切换到Error,出现错误的地方源头一般在log信息最下面

报错信息

错误提示没有一个Intent可以响应我们的操作,这是因为在Android中,每个Intent只能指定一个action,可以指定多个category

隐式意图的使用场景

一般用于启动不同应用中的Activity,常用的,我们可以启动系统自带的应用。比如你的程序中需要展示一个网页,这时候你不必自己实现这个功能,可以调用系统自带的浏览器来实现:

public class FirstActivity extends AppCompatActivity{
    private final String INTENT_ACTION = "com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY";
    private final String INTENT_ACTION_TEMP = "com.snaptech.activitytest.START_ACTION_SECOND_ACTIVITY_TEMP";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstactivity_layout);

        Button button = (Button) findViewById(R.id.btn_button);
    }

    public void onButtonClick(View view){
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://blog.youkuaiyun.com/wudongjiang333"));
        startActivity(intent);
    }
}

结果:
隐式意图

上述代码中,可能你会对setData()陌生,它接收一个Uri对象,主要用于指定当前Intetn正在操作的数据,而这些数据通常都是以字符串的形式传入到Uri.parse()方法中解析产生的。与此对应,我们可以在中在配置一个标签,用于更精确地指定当前活动能够响应什么类型的数据。可以配置一下内容:

  • android:scheme:用于指定数据的协议部分,如上例中的http部分。
  • android:hose:用于指定数据的主机名部分,如上例中的blog.youkuaiyun.com
  • android:port:用于指定数据的端口部分,一般紧随在主机名之后。
  • android:path:用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容
  • android:mimeType:用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

如果系统中存在多个Activity的intent-filter同时与你的intent匹配,那么系统会显示一个对话框,列出所有匹配的Activity,由用户选择启动哪一个

匹配的所有Activity列表

本节暂时介绍到这里,下一节主要介绍Activity之间的通信、Activity的生命周期、Activity的启动模式等内容

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值