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中新建项目默认创建的代码为:

@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 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)。

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

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

  1. 通过Activity的别名隐式启动
//隐式启动系统Activity
//参数1:字符串(某Activity的别名)
Intent it = new Intent("com.example.test.ACTION_START");  
startActivity(it);
<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. 通过别名和自定义的种类隐式启动
Intent it = new Intent("com.example.test.ACTION_START");  
//添加自定义的种类
intent.addCategory("com.example.test.MY_CATEGORY");
startActivity(it);
<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对象传递进去:

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. 响应用户指定的数据类型
<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方法来实现

// 发送方 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应用场景
StandardStandard启动模式适用于一般的Activity,不声明,则默认使用该模式,Activity跳转多少次,需要多少次返回FLAG_ACTIVITY_NEW_TASK:作用是为Activity指定 “SingleTask”启动模式一般的activity场景
SingleTopSingleTop启动模式 栈顶复用模式,如果Activity调用时处于我顶,则不再创建实例,调用方法onNewlntent,否则同Standard一致。FLAG_ACTIVITY_SINGLE_TOP:作用是为Activity指定 “SingleTop”启动模式消息聊天界面、新闻推送消息
SingleTaskSingleTask启动模式如果Activity已经再找中,则其栈上面的Activity弹出栈,使其置于栈顶位置,调用方法onNewlntent。FLAG_ACTIVITY_CLEAN_TOP :具有此标记位的Activity,启动时会将与该Activity在同一任务栈的其他Activity出栈。一般与SingleTask启动模式一起出现。它会完毕SingleTask的作用。但事实上SingleTask启动模式默认具有此标记位的作用浏览器应用、Home页面、重置密码返回界面
SingleInstanceSingleInstance是全局单例模式+,是一种加强的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示例代码如下:

    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的布局文件:
    <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的示例代码如下:
    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的示例代码如下:

    <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的生命周期日志了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值