当前位置: 首页 > news >正文

Android 四大组件——Activity

目录

一、Activity 基础概念

二、Activity 生命周期

1. 生命周期回调方法

2. 生命周期场景

触发或不触发 onPause/onStop 的 UI 组件(本质是附属的还是独立的)

三、Activity / ActionBarActivity / AppCompatActivity的区别:

四、onCreate()一个参数和两个参数的区别:

详细对比分析

1.单参数代码示例

2.双参数代码示例

五、Activity间的数据相互传递

六、关闭所有Activity和退出App

1.关闭所有Activity

2.退出App

七、屏幕旋转对Activity的影响

1.使用 onSaveInstanceState() 保存临时状态(最常用)

2.手动处理配置变更(阻止销毁重建)

3.固定 Activity 屏幕方向的方法

3.1 在 AndroidManifest.xml 中配置(推荐)

3.2 在 Java 代码中动态设置

4.使用 ViewModel + LiveData(架构组件推荐)

与其他方案的对比

八、启动模式

九、设置Activity全屏的方法

1.代码隐藏ActionBar

2.通过requestWindowFeature设置

3.通过AndroidManifest.xml的theme


一、Activity 基础概念

Activity 是 Android 应用的核心组件之一,它代表一个单一的、用户可交互的屏幕。Activity可以理解成一个绘制用户界面的窗口, 而这个窗口可以填满整个屏幕,也可能比屏幕小或者浮动在其他窗口的上方!

注意:必须在 AndroidManifest.xml 文件中进行声明。

二、Activity 生命周期

这是 Activity 最核心的概念,它描述了 Activity 从创建到销毁的整个过程。系统通过调用一系列生命周期回调方法来管理 Activity。

1. 生命周期回调方法

  • onCreate()必须实现。Activity 第一次创建时调用。在此进行一次性初始化,如加载布局 (setContentView)、绑定数据等。

  • onStart():Activity 对用户可见之前调用。此时 Activity 已进入前台,但可能还无法与用户交互(例如被一个对话框部分覆盖)。

  • onResume():Activity 开始与用户交互之前调用。此时 Activity 位于 Activity 堆栈的顶部,接收用户输入。应用的核心功能通常在这里恢复。

  • onPause():当系统准备启动或恢复另一个 Activity 时调用。在此应提交未保存的更改、释放占用资源的系统组件(如广播接收器),但操作要轻量快速,否则会拖慢下一个 Activity 的启动。

  • onStop():Activity 对用户完全不可见调用。可以执行重量级的关闭操作,如将数据写入数据库。

  • onRestart():在 onStop() 之后,Activity 重新启动时调用,后接 onStart()

  • onDestroy():Activity被销毁之前调用。这是 Activity 收到的最后一个回调。可能是因为 Activity 正常结束,也可能是因为系统为节省空间而将其销毁。

2. 生命周期场景

  • 正常启动:A onCreate -> A onStart -> A onResume

  • 打开新 Activity B(A 完全被覆盖):A onPause -> B onCreate -> B onStart -> B onResume -> A onStop

  • 从 B 返回 A:B onPause -> A onRestart -> A onStart -> A onResume -> B onStop -> B onDestroy

  • 按返回键退出 A:A onPause -> A onStop -> A onDestroy

  • 屏幕旋转/配置更改当前 Activity 会被销毁并重建。A onPause -> A onStop -> A onDestroy -> A onCreate -> A onStart -> A onResume

另外AlertDialog和PopWindow是不会触发onPause(),onStop()回调方法!!!

AlertDialog 和 PopupWindow 默认不会触发其所属 Activity 的 onPause() 和 onStop() 回调。 这是因为它们被系统归类为同一窗口内部的UI元素,而不是一个新的、独立的“用户界面”。它们附着在所属 Activity 的窗口之上。它们与 Activity 共享同一个 “UI上下文” 和 “焦点栈”

触发或不触发 onPause/onStop 的 UI 组件(本质是附属的还是独立的

组件类型默认行为原因
Activity触发下层 Activity 的 onPause/onStop创建了新的顶级窗口,抢夺了焦点和可见性。
AlertDialog, PopupWindow, DialogFragment不触发 onPause/onStop附属窗口,与 Activity 共享同一UI上下文和焦点栈。
Spinner, Menu, Snackbar, Toast不触发 onPause/onStop属于应用内弹出的临时UI,本质是 PopupWindow 或系统提示。
配置为系统悬浮窗的 PopupWindow触发 onPause/onStop窗口类型改变为 TYPE_SYSTEM_ALERT 等,成为独立的顶级窗口

三、Activity / ActionBarActivity / AppCompatActivity的区别:

  • Activity:是 Android 框架原始的、最基础的基类。

  • ActionBarActivity:是 过时 的 Support Library 类,用于在旧版 Android 上实现 Material Design 风格的 ActionBar。

  • AppCompatActivity:是 现代、官方推荐 的 Support Library / AndroidX 类,用于在旧版 Android 上实现 Material Design 及其最新特性,是 ActionBarActivity 的直接替代品。

简单来说,它们的演进路径是:Activity -> ActionBarActivity (已废弃) -> AppCompatActivity (当前标准)。

下面我们通过一个表格和详细解释来说明三者的区别。

特性Activity (原生)ActionBarActivity (已废弃)AppCompatActivity (现代)
所属库android.app.Activity (Android Framework)android.support.v7.app.ActionBarActivity (Old Support Library)android.support.v7.app.AppCompatActivity (Old Support Lib)

androidx.appcompat.app.AppCompatActivity (AndroidX)
引入目的提供基本的 Activity 组件功能。在 Android 3.0 (API 11) 之前版本上提供 ActionBar 兼容支持。提供更全面的 Material Design 特性向后兼容,并成为应用的基础类。
ActionBarAPI 11+ 原生支持。主要功能:在低版本上提供 ActionBar。提供并增强了 ActionBar 支持,并演变为 Toolbar 的官方支持载体。
Material DesignAPI 21+ 原生支持。有限的 Material Design 样式。完整支持:将 Material Design 样式和组件(如 Toolbar)向后兼容到 API 7+。
主题要求可以使用任何主题,如 Theme.Material必须使用/继承 Theme.AppCompat 系列主题。必须使用/继承 Theme.AppCompat 系列主题。
现状与建议仍在使用,但对于需要 Material Design 一致性的应用不推荐。完全废弃。不应在新项目中使用,老项目应迁移。官方强烈推荐 和 现代开发的标准选择

为了兼容低版本” 是 AppCompatActivity 最核心、最根本的设计目标和存在意义。

四、onCreate()一个参数和两个参数的区别:

  • onCreate(Bundle savedInstanceState):这是你最常见、必须实现标准生命周期方法。即使两个参数的onCreate()实现了,也需要实现onCreate(Bundle savedInstanceState)。

  • onCreate(Bundle savedInstanceState, PersistableBundle persistentState):这是一个可选的重载方法,用于支持 “持久性” 的 Activity,允许它在设备重启后仍能恢复状态。在实际开发中极少使用。

详细对比分析

特性onCreate(Bundle savedInstanceState)onCreate(Bundle savedInstanceState, PersistableBundle persistentState)
方法签名一个参数两个参数
API 级别从 API 1 开始存在从 API 21 (Android 5.0) 开始引入
使用场景所有 Activity 的标准入口点。用于处理常规的初始化,如设置布局、绑定数据。仅用于声明了 android:persistableMode="persistAcrossReboots" 的 Activity。
数据恢复范围恢复因 配置变更 或 系统资源紧张被杀死 时的临时状态。除了恢复上述状态,还能恢复在 设备关机再开机(重启) 后的持久状态。
数据持久性临时性。数据保存在内存中,系统杀死进程后,这些数据就丢失了。持久性。数据会写入磁盘,即使设备重启,数据依然存在。
适用情况绝大多数应用场景。如恢复编辑框的文本、列表的滚动位置等。极少数特殊场景。如系统设置、Launcher、或需要记录用户操作流程且不怕重启的应用。
如何保存数据在 onSaveInstanceState(Bundle outState) 中保存数据。除了 onSaveInstanceState,还需要在 onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) 中保存持久化数据。

1.单参数代码示例

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);EditText editText = findViewById(R.id.editText);// 检查是否有之前保存的状态需要恢复if (savedInstanceState != null) {String savedText = savedInstanceState.getString("KEY_EDIT_TEXT");editText.setText(savedText);}
}// 必须重写此方法来保存临时状态
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);outState.putString("KEY_EDIT_TEXT", editText.getText().toString());
}

2.双参数代码示例

要使用这个重载方法,你必须先在 AndroidManifest.xml 中为该 Activity 声明一个属性

<activityandroid:name=".MyPersistableActivity"android:persistableMode="persistAcrossReboots" />

两个 Bundle 参数的区别

  • savedInstanceState:和单参数版本一样,用于存储临时性状态

  • persistentState:这是一个 PersistableBundle 对象,用于存储持久性状态。这个状态会被写入磁盘的 /data/system/procstats 目录下,即使设备关机再开机,这个数据依然存在。

// 在 AndroidManifest.xml 中声明了 android:persistableMode="persistAcrossReboots"
public class MyPersistableActivity extends AppCompatActivity {private int mPersistentCounter = 0;@Overridepublic void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {super.onCreate(savedInstanceState, persistentState);setContentView(R.layout.activity_persistable);// 从 persistentState 中恢复持久化数据if (persistentState != null) {mPersistentCounter = persistentState.getInt("PERSISTENT_COUNTER", 0);}Button button = findViewById(R.id.button);button.setOnClickListener(v -> {mPersistentCounter++;// 持久化数据不会自动保存,需要手动触发// 通常会在 onPause 或 onStop 中调用 onSaveInstanceState});}// 重写此方法来保存持久化数据@Overridepublic void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {super.onSaveInstanceState(outState, outPersistentState);// 将需要持久化的数据存入 outPersistentStateoutPersistentState.putInt("PERSISTENT_COUNTER", mPersistentCounter);}
}

单参数的 onCreate 是用来“恢复现场”的,而双参数的 onCreate 是用来“时光倒流”的

五、Activity间的数据相互传递

传递:A-->B

在使用Bundle传递数据时,要注意,Bundle的大小是有限制的 < 0.5MB,如果大于这个值 是会报TransactionTooLargeException异常的!!!

传回:A<--B

这个在之前的 Intent 章节提到过,相关内容可以查看上一章。

六、关闭所有Activity和退出App

1.关闭所有Activity

有时我们可能会打开了很多个Activity,突然来个这样的需求,在某个页面可以关掉 所有的Activity并退出程序!好吧,下面提供一个关闭所有Activity的方法, 就是用一个list集合来存储所有Activity。

public class ActivityCollector {  public static LinkedList<Activity> activities = new LinkedList<Activity>();  public static void addActivity(Activity activity)  {  activities.add(activity);  }  public static void removeActivity(Activity activity)  {  activities.remove(activity);  }  public static void finishAll()  {  for(Activity activity:activities)  {  if(!activity.isFinishing())  {  activity.finish();  }  }  }  
}  

2.退出App

/** * 退出应用程序 */  
public void AppExit(Context context) {  try {  ActivityCollector.finishAll(); //暴力杀死后台进程 ActivityManager activityMgr = (ActivityManager) context  .getSystemService(Context.ACTIVITY_SERVICE);  activityMgr.killBackgroundProcesses(context.getPackageName());  System.exit(0);  } catch (Exception ignored) {}  
}  

调用 killBackgroundProcesses() 方法,传入当前应用的包名,强制杀死该应用的所有后台进程

七、屏幕旋转对Activity的影响

屏幕旋转是 配置变更 中最典型的例子,当发生旋转后会销毁与重建。

出现的问题:

  • Activity 中所有非持久化的成员变量和数据都会丢失,因为对象被销毁了。
  • 用户体验中断:正在播放的视频、动画会中断,滚动列表的位置会重置,输入框的焦点会丢失等。

1.使用 onSaveInstanceState() 保存临时状态(最常用)

这是最基本也是必须掌握的方案。系统在销毁 Activity之前会调用此方法,让你有机会保存临时状态。

//保存状态
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState); // 必须调用父类方法!// 将需要恢复的数据存入BundleoutState.putInt("KEY_SCORE", mCurrentScore);outState.putString("KEY_INPUT_TEXT", mUserInputText);
}//恢复状态
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 检查是否有之前保存的状态if (savedInstanceState != null) {mCurrentScore = savedInstanceState.getInt("KEY_SCORE", 0);mUserInputText = savedInstanceState.getString("KEY_INPUT_TEXT", "");// 恢复UI状态,比如设置EditText的文本EditText editText = findViewById(R.id.editText);editText.setText(mUserInputText);}
}

注意: onSaveInstanceState 主要用于保存轻量级的、瞬时的 UI 状态。不适合保存大量数据(如Bitmap)或需要持久化的数据。

2.手动处理配置变更(阻止销毁重建)

你可以告知系统:“这个配置变更由我自己处理,你不要销毁我的 Activity”。

在 AndroidManifest.xml 中为 Activity 配置 android:configChanges 属性。

<activityandroid:name=".MainActivity"android:configChanges="orientation|screenSize|keyboardHidden" />
  • orientation:屏幕方向

  • screenSize:屏幕尺寸(API 13以上必需,因为旋转也涉及尺寸变化)

  • keyboardHidden:键盘可用性改变

效果:

  • 设置之后,屏幕旋转时 Activity 不会被销毁重建

  • 取而代之,系统会调用 onConfigurationChanged(Configuration newConfig) 方法。

@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {// 切换到横屏,可以在这里手动调整UILog.d("Orientation", "Now in Landscape");} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {// 切换到竖屏Log.d("Orientation", "Now in Portrait");}
}

优缺点:

  • 优点:Activity 不会重建,所有成员变量都得以保留,用户体验无缝。

  • 缺点

    • 你必须自己处理所有UI更新。例如,如果你为横竖屏准备了不同的布局(layout-land 和 layout-port),系统不会自动切换,你需要手动调用 setContentView 并重新初始化所有视图,这非常繁琐且容易出错。

    • 不推荐作为常规解决方案,仅适用于确实不希望UI被重建的特殊场景(如游戏、摄像头预览)。假如在特定场景下使用,如打开后必须使用横屏/竖屏。我们就可以看看下面的方法。

3.固定 Activity 屏幕方向的方法

3.1 在 AndroidManifest.xml 中配置(推荐)

这是最常用、最简洁的方式,在应用清单文件中为 Activity 声明屏幕方向。

<activityandroid:name=".MainActivity"android:screenOrientation="portrait" /> <!-- 固定为竖屏 --><activityandroid:name=".MainActivity"android:screenOrientation="landscape" /> <!-- 固定为横屏 -->

3.2 在 Java 代码中动态设置

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 固定为竖屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);// 或者固定为横屏// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);setContentView(R.layout.activity_main);}
}

4.使用 ViewModel + LiveData(架构组件推荐)

这是 现代 Android 开发中最推荐、最优雅的解决方案ViewModel 的设计目的就是存放和管理与UI相关的数据,并且它的生命周期比 Activity 更长。

ViewModel 在配置变更(如旋转)中会存活下来!

// 1. 创建ViewModel
public class MyViewModel extends ViewModel {private MutableLiveData<Integer> currentScore = new MutableLiveData<>(0);private MutableLiveData<String> userInput = new MutableLiveData<>("");public LiveData<Integer> getCurrentScore() {return currentScore;}public void setScore(int score) {currentScore.setValue(score);}public LiveData<String> getUserInput() {return userInput;}public void setUserInput(String input) {userInput.setValue(input);}
}// 2. 在Activity中使用
public class MainActivity extends AppCompatActivity {private MyViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取ViewModel(如果是旋转后重建,会拿到同一个实例)viewModel = new ViewModelProvider(this).get(MyViewModel.class);// 观察LiveData,数据变化时自动更新UIviewModel.getCurrentScore().observe(this, score -> {TextView scoreView = findViewById(R.id.scoreView);scoreView.setText("Score: " + score);});viewModel.getUserInput().observe(this, input -> {EditText editText = findViewById(R.id.editText);if (!editText.getText().toString().equals(input)) {editText.setText(input);}});findViewById(R.id.button).setOnClickListener(v -> {// 更新ViewModel中的数据,观察者会自动触发UI更新viewModel.setScore(viewModel.getCurrentScore().getValue() + 1);});}
}

优势:

  • 数据与UI分离:Activity 只负责显示和交互,数据由 ViewModel 持有。

  • 自动生命周期管理:无需手动保存和恢复,代码更简洁。

  • 完美的数据持久性:屏幕旋转对用户完全无感,数据一直都在。

与其他方案的对比

方案适用场景实现复杂度用户体验
固定屏幕方向不需要横竖屏切换的应用⭐☆☆☆☆ (非常简单)一致但不够灵活
onSaveInstanceState需要保存简单状态的应用⭐⭐☆☆☆ (简单)有短暂的中断
ViewModel现代应用,数据驱动的UI⭐⭐⭐☆☆ (中等)几乎无缝
configChanges特殊场景,如游戏、相机⭐⭐⭐⭐☆ (复杂)完全无缝

八、启动模式

接下来我们来详细地讲解下四种加载模式: 他们分别是:standard(默认),singleTopsingleTasksingleInstance 

在 AndroidManifest.xml 中通过 android:launchMode 设置。

  1. standard(默认):每次启动都会创建一个新的 Activity 实例。一个任务中可以有多个相同 Activity 的实例。

  2. singleTop:如果要启动的 Activity 已经位于任务栈顶,则不会创建新实例,而是调用其 onNewIntent() 方法。否则创建新实例。适用于防止重复启动同一个界面(如通知点击)。

  3. singleTask:系统会创建一个新任务,并将该 Activity 实例化为新任务的根 Activity。如果该 Activity 的实例已存在于一个独立的任务中,系统会将该任务转到前台,并调用 onNewIntent()一个任务中只存在一个该 Activity 的实例。常用于应用的主页。

  4. singleInstance:与 singleTask 类似,但持有该 Activity 的任务只能有这一个 Activity。任何从该 Activity 启动的新 Activity 都会在另一个任务中打开。适用于需要单独任务栈的场景(如闹钟)。

使用 Intent Flag 动态控制
你也可以在 Intent 中设置 Flag 来动态控制启动行为,其优先级高于 launchMode

  • FLAG_ACTIVITY_NEW_TASK:在新任务中启动 Activity。

  • FLAG_ACTIVITY_SINGLE_TOP:等同于 singleTop

  • FLAG_ACTIVITY_CLEAR_TOP:如果目标 Activity 已在当前任务中,则会销毁位于它之上的所有 Activity,使其位于栈顶。

九、设置Activity全屏的方法

1.代码隐藏ActionBar

在Activity的onCreate方法中调用getActionBar.hide();即可

2.通过requestWindowFeature设置

requestWindowFeature(Window.FEATURE_NO_TITLE); 该代码需要在setContentView ()之前调用,不然会报错!!!

注: 把 requestWindowFeature(Window.FEATURE_NO_TITLE);放在super.onCreate(savedInstanceState);前面就可以隐藏ActionBar而不报错。

3.通过AndroidManifest.xml的theme

在需要全屏的Activity的标签内设置 theme = @android:style/Theme.NoTitleBar.FullScreen

http://www.dtcms.com/a/541465.html

相关文章:

  • 照片书哪个网站做的好哪家网站开发培训好
  • wordpress小说网站模板下载地址光辉网络 石家庄网站建设
  • 网站建设可信赖环球资源网的网站特色
  • 西安网站开发高端网站开发中企动力是干嘛的
  • 浅谈什么是微前端
  • AtCoder Beginner Contest 429(ABCDEF)
  • 好用的GEO优化引擎服务商
  • 做网站那个平台网站制作网站建设案例
  • 搜索引擎主题网站模板网络架构有哪几层
  • Linux 驱动开发中,主设备号和次设备号不同的两个驱动能否正常工作
  • 人和AI的分工模式!
  • 模板网站与 定制网站的 对比中企动力主要做什么的
  • ECharts 3D柱状图组件开发实战:Bar3D.vue 完整解析
  • 手机App上的轮播图是如何实现的—探究安卓轮播图
  • Day71 MQTT数据上传与ARM端交叉编译部署全链路实践
  • 2024年 5月 每日分享
  • 漯河英文网站建设创建私人网站
  • 网站开发学哪一个好电子商务网站建设模板
  • 5.4 大数据方法论与实践指南-存储-安全合规
  • 凡科建设网站图片怎么删除专门做自由行的网站
  • 车辆智能检索与缉查布控
  • Cesium中如何修改geojson数据的颜色
  • 51c大模型~合集42
  • C++语法—类的声明和定义
  • 企业网站建设方案资讯查询公司的网站
  • 高端企业网站建设公司免费网站代理访问
  • JavaEE初阶——多线程(4)线程安全
  • 杭州网站推广营销服务深圳做美颜相机的公司
  • 什么样 个人网站 备案适合做网站的软件有哪些
  • 做设计在哪个网站上找高清图青岛做物流网站