Android四大组件之Activity详解

Android四大组件之Activity

1 概念

Activity是Android的四大组件之一,同时它也是Android应用中最常见的组件之一。一个应用通常会有多个Activity,它主要负责与用户进行交互,并向用户呈现出应用此时的状态,不同的Activiy呈现给用户不同的操作体验。其实每当我们打开一个Android的app,我们都会接触到它。他其实就相当于一个屏幕,上面承载着我们所能看到和接触到的不同的组件。

2 创建Activity

  1. 在Android studio里面新建工程->右键单击 com.example.myapplication,选择新建一个Activity,选择Empty Views Activity即可,勾选上对应的Generate a Layout File(自动生成对应的布局文件)和Launcher Activity(Gradle自动将该Activity作为启动界面,也可以自行在ManifestXML中进行配置)

Android Studio中新建项目默认创建的代码为:

java 复制代码
@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    EdgeToEdge.enable(this);  
    setContentView(R.layout.activity_main);  
    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {  
        Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());  
        v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);  
        return insets;  
    });  
}  

}

初始自动生成布局文件xml代码为:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="Day1_demo.MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

点击MainActivity运行即可。

3 启动方式

3.1 显示启动

显式启动比较简单,首先创建一个Intent,指定应用程序上下文和需要启动的Activity,然后调用startActivity来启动新的Activity(显式启动是指明确指定要启动的目标Activity,常用于启动同一个应用程序中的Activity)。

java 复制代码
//启动Activity
Intent it = new Intent(this, SecondActivity.class);
startActivity(it);
3.2 隐式启动

隐式启动是指没有明确指定目标Activity,而是通过Intent的action、category、data等属性来描述要启动的目标Activity。系统会根据这些条件在AndroidManifest.xml中查找匹配的Activity,并启动它。

  1. 通过Activity的别名隐式启动
java 复制代码
//隐式启动系统Activity
//参数1:字符串(某Activity的别名)
Intent it = new Intent("com.example.test.ACTION_START");  
startActivity(it);
xml 复制代码
<activity android:name=".SecondActivity">
    <intent-filter>
        <!--取别名-->
        <action android:name="com.example.test.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>

    </intent-filter>
</activity>
  1. 通过别名和自定义的种类隐式启动
java 复制代码
Intent it = new Intent("com.example.test.ACTION_START");  
//添加自定义的种类
intent.addCategory("com.example.test.MY_CATEGORY");
startActivity(it);
xml 复制代码
<activity android:name=".SecondActivity">
    <intent-filter>        
    	<action android:name="com.example.test.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="com.example.test.MY_CATEGORY"/>
    </intent-filter>
</activity>
  1. 根据用户的数据类型打开相应的Activity

Intent.ACTION_VIEW是Android系统内置的一个动作,通过Uri.parse()方法解析后,再调用Intent.setData()方法将这个Uri对象传递进去:

java 复制代码
Intent it = new Intent("Intent.ACTION_VIEW");  
it.setData(Uri.parse("https://www.baidu.com"));
startActivity(it);

//参数1:字符串(某Activity的别名)
//参数2:打开的路径,通过协议来具体的确定打开什么Activity
Intent it2 = new Intent("Intent.ACTION_VIEW", Uri.parse("https://www.baidu.com")); 
startActivity(it2);

Intent it3 = new Intent("Intent.ACTION_DIAL", Uri.parse("tel:18812341234")); 
startActivity(it3);
  1. 响应用户指定的数据类型
xml 复制代码
<activity android:name=".SecondActivity">
    <intent-filter tools:ignore="AppLinkUrlError">        
    <action android:name="com.example.test.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="https">
    </intent-filter>
</activity>
   

这里通过android:scheme指定了数据的协议必须的https协议,这样此Activity就能和浏览器一样,响应一个打开网页的Intent了。

3.3 Intent数据传递

Intent 是 Android 中用于组件间通信的重要机制,在 Activity 跳转时传递数据是最常见的用法之一,传递简单数据通常通过Intent的putExtra和getExtras方法来实现

java 复制代码
// 发送方 Activity
Intent intent = new Intent(CurrentActivity.this, TargetActivity.class);
intent.putExtra("key_string", "字符串数据");
intent.putExtra("key_int", 100);
intent.putExtra("key_boolean", true);
startActivity(intent);

// 接收方 Activity
String strValue = getIntent().getStringExtra("key_string");
int intValue = getIntent().getIntExtra("key_int", 0); // 0是默认值
boolean boolValue = getIntent().getBooleanExtra("key_boolean", false);
  • 常用 putExtra() 方法:

    方法 说明
    putExtra(String name, String value) 传递字符串
    putExtra(String name, int value) 传递整型数据
    putExtra(String name, boolean value) 布尔值
    putExtra(String name, float value) 浮点数
    putExtra(String name, Serializable value) 可序列化对象
    putExtra(String name, Parcelable value) 可包裹化对象
    putStringArrayListExtra() 字符串列表
    putIntegerArrayListExtra() 整型列表
    • 通过Intent传递的数据大小有限制(通常为1MB-8K)。​ 将大数据存储在文件或数据库中,并在Intent中传递引用(如文件路径、数据库ID)。

    • 返回数据-startActivityForResult​

      Activity在finish的时候需要向上一个Activity传值的时候,我们就可以使用startActivityForResult。比如打开相册选取照片,拍照,关闭页面需要返回一个参数给打开我们的页面。​ 使用startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新Activity关闭前需要向前面的Activity返回数据需要使用系统提供的setResult(int resultCode, Intent data),前面的Activity中通过onActivityResult(int requestCode, int resultCode, Intent data)方法接受回传值。

4 生命周期

周期即活动从开始到结束所经历的各种状态。生命周期即活动从开始到结束所经历的各个状态。从一个状态到另一个状态的转变,从无到有再到无,这样一个过程中所经历的状态就叫做生命周期。从进程优先级的角度分析,各生命周期状态可以表现出Activity所在进程的状态(前台进程、可见进程、后台进程、缓存进程),设计者将这些状态变化的时机抛出来让开发者知晓,在不同状态做一些数据加载、保存等业务逻辑。 生命周期经典流程图:

生命周期 状态 说明 注意事项
onCreate 创建 当活动第一次被创建时调用 可做初始化工作,如setViewContent界面资源、初始化数据,此方法的传参Bundle为该Activity上次被异常情况销毁时保存的状态信息
onStart 启动 当活动即将可见时调用 Activity可见但无法和用户交互:用户可以看到活动的界面,但此时活动还未在前台获得焦点(即还没有准备好与用户交互)
onResume 获得焦点 当活动可见时进行调用 Activity可见且在前台并开始活动
onPause 即将停止 其他活动获得焦点时进行调用 Activity切换时,旧Activity的onPause会先执行,然后才会启动新的Activity,可做数据存储、停止动画等操作
onStop 停止 当活动不再可见时调用 可做稍微重量级回收工作,如取消网络连接、注销广播接收器等,新Activity是透明主题时,旧Activity都不会走onStop
onDestroy 即将摧毁 当活动即将被销毁时调用 可做回收工作、资源释放
onRestart 重新启动 当活动再次可见时调用 由后台切换到前台,由不可见到可见

5 启动模式

在Android应用程序中,Activity是用户界面的基本构建模块。为了管理Activity的启动和导航,Android引入了任务栈(Task Stack)的概念。每个任务栈(Task)通常对应一个用户正在与之交互的应用程序或应用程序的一部分。​ 每个任务栈包含了一系列的 Activity 实例,当前显示的 Activity 总是位于栈顶,用户可以通过按下返回键来关闭当前 Activity,并将其从任务栈中移除。

启动模式 说明 使用方法2中的Activity 的 Flags 应用场景
Standard Standard启动模式适用于一般的Activity,不声明,则默认使用该模式,Activity跳转多少次,需要多少次返回 FLAG_ACTIVITY_NEW_TASK:作用是为Activity指定 "SingleTask"启动模式 一般的activity场景
SingleTop SingleTop启动模式 栈顶复用模式,如果Activity调用时处于我顶,则不再创建实例,调用方法onNewlntent,否则同Standard一致。 FLAG_ACTIVITY_SINGLE_TOP:作用是为Activity指定 "SingleTop"启动模式 消息聊天界面、新闻推送消息
SingleTask SingleTask启动模式如果Activity已经再找中,则其栈上面的Activity弹出栈,使其置于栈顶位置,调用方法onNewlntent。 FLAG_ACTIVITY_CLEAN_TOP :具有此标记位的Activity,启动时会将与该Activity在同一任务栈的其他Activity出栈。一般与SingleTask启动模式一起出现。它会完毕SingleTask的作用。但事实上SingleTask启动模式默认具有此标记位的作用 浏览器应用、Home页面、重置密码返回界面
SingleInstance SingleInstance是全局单例模式+,是一种加强的SingleTask模式。它除了具有它所有特性外,还加强了一点:具有此模式的Activity仅仅能单独位于一个任务栈+中 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
:具有此标记位的Activity不会出如今历史Activity的列表中 Launcher、锁屏键(只用一个的应用)
  • 启动模式的使用方法
  1. 在 Manifest.xml中指定Activity启动模式,设置launchMode为对应的值

  2. 启动Activity时。在Intent中指定启动模式去创建Activity

一种动态的启动模式,在new 一个Intent后,通过Intent的addFlags方法去动态指定一个启动模式若两者同一时候存在,以静态启动方式为准。

实操demo:

  • 要求:实现一个简易的登录应用 (LoginDemoApp)​,通过完成一个简单的登录跳转场景,巩固Activity的生命周期理解、启动方式、数据传递和返回处理(生命周期使用Log.d进行查看)。​

    • 登录页面 (LoginDemoApp):​ 包含:用户名 (EditText) 和 密码 (EditText)和一个登录按钮 (Button)。​

    • 点击登录按钮:​检查用户名和密码是否为空。为空,使用Toast提示用户;不为空,则显式启动 WelcomeActivity。​

    • 欢迎页面 (WelcomeActivity):​接收从LoginDemoApp传递过来的用户名。​显示一条欢迎信息,欢迎回来,[用户名]!。​

    • 返回处理 (Back Navigation):​在WelcomeActivity中,用户按下设备的返回键时:​使用Toast提示用户"再按一次返回键退出"。​若2秒内再次按下返回键,则关闭当前Activity并退出应用;超过2秒才再次按下,则Toast提示消失,需要重新按两次才能退出。

  • 示例源码:

    • LoginDemoApp.java示例代码如下:

    java 复制代码
    public class LoginDemoApp extends AppCompatActivity {
        private static final String TAG = "LoginDemoApp";
        private EditText usernameEditText, passwordEditText;
        private Button loginButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login_demo_app);
    
            // 初始化控件
            usernameEditText = findViewById(R.id.editTextUsername);
            passwordEditText = findViewById(R.id.editTextPassword);
            loginButton = findViewById(R.id.buttonLogin);
    
            // 设置登录按钮点击事件
            loginButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String username = usernameEditText.getText().toString().trim();
                    String password = passwordEditText.getText().toString().trim();
    
                    // 检查用户名和密码是否为空
                    if (username.isEmpty() || password.isEmpty()) {
                        Toast.makeText(LoginDemoApp.this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
                    } else {
                        // 跳转到欢迎页面
                        Intent intent = new Intent(LoginDemoApp.this, WelcomeActivity.class);
                        intent.putExtra("USERNAME", username); // 传递用户名
                        startActivity(intent);
                        finish();
                    }
                }
            });
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG, "onStart: finish!");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.d(TAG, "onPause: finish!");
    
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.d(TAG, "onStop: finish!");
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
            Log.d(TAG, "onRestart: finish!");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy: finish!");
        }
    }
    • activity_login_demo_app.xml的布局文件:
    xml 复制代码
    <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:gravity="center" 
    android:padding="16dp"> 
    <EditText 
    android:id="@+id/editTextUsername" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:hint="用户名" /> 
    <EditText 
    android:id="@+id/editTextPassword" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:hint="密码" 
    android:inputType="textPassword" /> 
    <Button 
    android:id="@+id/buttonLogin" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="登录" 
    android:layout_marginTop="16dp" /> 
    </LinearLayout>
    • WelcomeActivity.java的示例代码如下:
java 复制代码
    public class WelcomeActivity extends AppCompatActivity {
        private static final String TAG = "WelcomeActivity";
        private boolean isBackPressedOnce = false; // 标记是否按过返回键
        private Handler handler = new Handler();
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_welcome);
        
        // 获取从 LoginDemoApp 传递过来的用户名
        String username = getIntent().getStringExtra("USERNAME");
        
        // 显示欢迎信息
        TextView welcomeTextView = findViewById(R.id.textViewWelcome);
        welcomeTextView.setText("欢迎回来," + username + "!");
        }
        
        @Override
        public void onBackPressed() {
            if (isBackPressedOnce) {
                super.onBackPressed();
                return;
            }
            this.isBackPressedOnce = true;
            Toast.makeText(this, "再按一次返回键退出", Toast.LENGTH_SHORT).show();
        
            // 2秒后重置 isBackPressedOnce
            handler.postDelayed(() -> isBackPressedOnce = false, 2000);
        }
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG, "onStart: finish!");
        }
        
        @Override
        protected void onPause() {
            super.onPause();
            Log.d(TAG, "onPause: finish!");
        
        }
        
        @Override
        protected void onStop() {
            super.onStop();
            Log.d(TAG, "onStop: finish!");
        }
        
        @Override
        protected void onRestart() {
            super.onRestart();
            Log.d(TAG, "onRestart: finish!");
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy: finish!");
        }
        
    }
  • activity_welcome.xml的示例代码如下:
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"
    android:padding="16dp">

    <TextView
        android:id="@+id/textViewWelcome"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:textStyle="bold"
        android:text="欢迎回来!" />
</LinearLayout>
  • activity从生命周期使用Log.d进行查看,在Android studio中logcat中过滤信息:level:debug tag:WelcomeActivity tag:welcomeactivity即可查看到activity的生命周期日志了。
相关推荐
小墙程序员11 分钟前
kotlin元编程(一)一文理解 Kotlin 反射
android·kotlin·android studio
fatiaozhang95271 小时前
创维智能融合终端DT741_移动版_S905L3芯片_安卓9_线刷固件包
android·电视盒子·刷机固件·机顶盒刷机
搬砖不得颈椎病3 小时前
Jetpack DataStore vs SharedPreferences:现代Android数据存储方案对比
android
auxor6 小时前
Android 窗口管理 - 窗口添加过程分析Client端
android
雨白6 小时前
HTTP协议详解(一):工作原理、请求方法与状态码
android·http
Yang-Never7 小时前
Kotlin -> object声明和object表达式
android·java·开发语言·kotlin·android studio
小白马丶7 小时前
Jetpack Compose开发框架搭建
android·前端·android jetpack
攻城狮Talk7 小时前
FocusParkingView清除旧Window焦点
android
狂浪天涯7 小时前
Android 16 显示系统 | 从View 到屏幕系列 - 8 | SurfaceFlinger 合成 (一)
android