Android 四大组件之活动(Activity)

写在前面

Activity是Android应用的重要组件,多数的编程语言中,程序是通过main()函数来启动的,但是在Android项目中我们找不到main()函数,这是因为Android App的启动方式为:通过Android系统来调用与其生命周期特定阶段相对应的特定回调方法来启动Activity实例中的代码。例如,当一个App被点击启动时,Android系统会创建你写的某个Acticity的实例,并调用其生命周期中的应得onCreate()和onStart()等方法,后面我们会具体介绍。本篇主要介绍一下Android中Activity的一些个人理解(本人新手,可能会有不准确的地方)。参考资料:《移动操作系统原理与实践》关东升,Android开发者文档:https://developer.android.google.cn/guide/components/activities/intro-activities?hl=zh_cn

创建活动

创建一个Activity需要包括两个步骤:
(1) 编写相应的Activity类(java文件)。
(2) 在AndroidManifest.xml文件中注册。
首先我们还是先创建一个Android Studio的项目工程,打开MainActivity.java文件,这里已经帮我们创建好了一个Activity。

package com.beihang.test;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

同时需要在Manifest文件中注册:首先需要声明Activity,作为Application的子元素:

<manifest ... >
      <application ... >
          <activity android:name=".ExampleActivity" />
          ...
      </application ... >
      ...
    </manifest >

这里android:name="…"是必要元素,指该Activity的名称,这个是不能够轻易更改的。必要时还可以添加一些其它的属性,查看Android开发文档可以知道。
其次还要声明意图过滤器(intent-filter),intent-filter是Android中一项强大的功能,它使得Android中的Activity不仅能够显式的被调用,还能够隐式启动,例如:你可以告诉Android系统,找到任何能够完成某一工作的Activity来启动,但不指定哪个Activity。

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity>

首先声明intent-filter子元素,这个子元素一般包括action子标签和可选的category和data子标签,组合在一起声明该Activity能够接受哪些意图**(Intent)**,可以通过符合过滤器的意图来调用此Activity。上述代码的三个标签分别说明:action标签说明该Activity能够发送信息; category标签说明Activity 能够接收启动请求;data标签指定此 Activity 可以发送的数据类型。具体如何通过意图启动Activity下面会提到。
创建完Activity和在Manifest文件中注册完之后,就可以在Activity中实现自己的逻辑了。

活动的生命周期

一个 Activity 在其生命周期中会经历多种状态。您可以使用一系列回调来处理状态之间的转换。首先祭出Activity声明周期的框图:
在这里插入图片描述
这里直接采用AndroidAPI的图。
首先活动主要有三种状态:运行状态、暂停状态、停止状态。对应关系分别为:运行状态是活动进入前台,位于栈顶,此时活动处于运行状态(onResume),运行状态的活动可以获得焦点,活动中的内容高亮显示;暂停状态是当其它活动进入前台,当前的活动不再位于栈顶,仍然可见但是变暗,此时活动处于暂停状态(onPause),不能获得焦点,系统内存较低时会回收暂停状态的活动;停止状态是当活动不再处于栈顶,被其他活动完全覆盖,不可见时处于停止状态(onStop),此时活动的成员变量值仍被保存,系统内存低时回收。
看框图可知,一个Activity启动的时候,其onCreate()、onStart()以及onResume()方法被调用,活动进入运行状态,当其它活动进入前台(栈顶)时该Activity的onPause()方法被调用,活动进入暂停状态,如果其它应用需要内存时杀死该进程,再次回到活动时又和启动时一样调用onCreate()、onStart()以及onResume()到运行状态;当Activity不再可见时,其onStop()方法被调用,活动进入停止状态,停止状态仍然可以在用户唤醒的时候调用onRestart()方法重新启动,在系统内存低的时候杀死进程。
可以编写下面一段代码来测试Android手机的Back按钮和Home按钮的区别。
需要注意的是onCreate()方法,它在整个Activity的生命周期中只执行了一次,所以一些启动相关的逻辑都需要编写在这里

package com.beihang.test;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "onCreate");
    }
    
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart");
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume");
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause");
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
    }
    
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart");
    }
}

这里我们在活动的每个回调方法中打印出调用信息,在Logcat中就能够实时查看Activity的运行状态了。实际运行过程中:App启动的时候,打印内容显示onCreate()、onStart()以及onResume()方法被调用;按home键,打印内容显示onPause()和onStop()方法被调用,活动进入停止状态;按Back键时,onPause()、onStop()和onDestroy()方法被调用,活动被系统销毁。这样我们很清楚看到一个Activity的声命周期以及不同状态切换下方法的回调。我们只需要在相应的回调方法中编写我们的逻辑就行了。更具体详细的Activity生命周期的内容参见官方文档。

不同Activity之间的转换

大多数项目不只有一个Activity,我们需要在不同的Activity中进行跳转。一个活动进入另一个活动有两种方法:startActivity()和startActivityForResult(),这两种方法都需要传入一个Intent对象,下面分别介绍:
(1)startActivity()
如果新启动的 Activity 不需要返回结果,则当前 Activity 可以通过调用 startActivity() 方法来启动它。

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

这里创建了一个Intent对象,其中构造方法的第二个参数是具体组件类名,通过这个参数可以指定需要启动的Activity,然后直接传入startActivity()方法就能够跳转至SignInActivity了。关于Intent的内容后面有时间再写一篇。
有的时候还希望将本Activity的某些数据传递到下个Activity中,例如发送电子邮件、短信等。这都是通过Intent对象来完成数据交流的。

Intent intent = new Intent(this, SignInActivity.class);
intent.putExtra("userId", txtUserid.getText().toString());
startActivity(intent);

这里通过Intent对象的putExtra()方法,该方法传递一个键-值对,然后可以在被启动的SignInActivity中获取意图和数据。

Intent it = this.getIntent();
Bundle bundle = it.getExtras();
String userId = bundle.getString("userId");

(2)startActivityForResult()
有时,您会希望在 Activity 结束时从 Activity 中获取返回结果。例如,您可以启动一项 Activity,让用户在联系人列表中选择一个人;当 Activity 结束时,系统将返回用户选中的人。这时候可以调用startActivityForResult(Intent intent, int requestCode)方法。第一个参数为Intent对象和上面startActivity()方法一样,第二个整型参数是请求编码,一般用来消除来自同一 Activity 的多次 startActivityForResult(Intent, int) 调用之间的歧义。此外,还要覆写onActivityResult(int requestCode, int resultCode, Intent)方法用于子级Activity结束时的回调,在这个方法内取得子级Activity传来的数据。
对于子级Activity来说需要在活动结束时调用setResult(int resultCode, Intent it)。举个例子:

btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent it = new Intent(this, SuccessActivity.class);
                startActivityForResult(it, 123);
            }
        });
...
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent it) {
        if (requestCode == 123) {
            if (resultCode == 4) {
                Log.v(TAG, resultCode + "received");
            }
        }
    }

在子级Activity中要调用setResult(int resultCode, Intent it)方法:

btnback.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setResult(4, (new Intent()).putExtra("userId", userid));
                this.finish();
            }
        });

这样在子活动返回时,回调方法onActivityResult()就会被调用,并执行相关操作。

总结

本片主要针对活动(Activity)进行了简要介绍,细节和其它高级的用法参见Android开发者文档。文章分为Activity的创建、生命周期、不同Activity之间跳转的两种方法。Activity是Android 项目中非常重要的组件,搞清楚程序运行的不同状态调用的不同回调方法才能够比较清楚的理解程序执行过程。文中还涉及了一些意图(Intent)的概念,有时间会写一篇关于Intent的文章。

发布了8 篇原创文章 · 获赞 3 · 访问量 2695

猜你喜欢

转载自blog.csdn.net/qq_41241926/article/details/104872988