版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android课程7Android生命周期学习目标AIMS了解Android系统的进程优先级的变化方式010203了解Android系统的四大基本组件了解Activity的生命周期中各状态的变化关系04掌握Activity事件回调函数的作用和调用顺序7.1Android组件Android系统有四个重要的组件,分别是Activity、Service、BroadcastReceiver和ContentproviderActivity是Android程序的主要界面组件,负责显示可视化的用户界面,并接收与用户交互所产生的界面事件,它类似于传统桌面应用中的窗口(但有着自己独特的生命周期和功能)。Android应用程序可以包含一个或多个Activity,一般在程序启动后会呈现一个Activity,用于提示用户程序已经正常启动。Activity在界面上的表现形式一般是全屏窗体,也可以是非全屏悬浮窗体或对话框7.1Android组件Service通常用于没有用户界面、但需要在后台长时间运行的任务。例如,播放MP3音乐时,使用Service可以在关闭播放器界面后继续播放音乐。通过公开Service的通信接口,用户可以控制音乐的播放、暂停和停止。BroadcastReceiver是用来接收并响应广播消息的组件。大部分广播消息由系统产生,例如时区改变、电池电量低或语言设置更改等,但应用程序也可以发送广播消息,例如数据下载完成等。ContentProvider是Android系统提供的共享数据机制,允许应用程序通过它访问其他应用程序的私有数据。私有数据可以是文件系统中的文件,也可以是存储在SQLite数据库中的数据。ContentProvider还支持权限控制,确保数据的安全访问7.2进程和优先级软件生命周期是软件从产生到废弃所历经的几个阶段,一般包括可行性分析、开发计划、需求分析与设计、编码、测试和维护等过程。Android应用程序生命周期与软件生命周期的定义不同,指的是在Android系统中从启动到终止的所有阶段,也就是Android程序启动到停止的全过程Android系统一般是运行在资源受限的硬件平台上,因此资源管理对Android系统至关重要。Android系统会主动管理资源,为了保证高优先级程序正常运行,可以在无任何警告的情况下终止低优先级程序,并回收其使用的系统资源。因此Android程序并不能控制自身的生命周期,而完全是由Android系统进行调度和控制的7.2进程和优先级Android系统尽可能的不主动终止应用程序,即使生命周期结束的程序也会保存在内存中,以便再次快速启动。但在内存紧张时,系统会根据进程的优先级清除进程,回收系统资源。Android系统中的进程优先级如图所示,优先级有高到低分别为前台进程、可见进程、服务进程、后台进程和空进程7.2进程和优先级(1)前台进程前台进程是与用户正在交互的进程。前台进程包含以下四种情况:进程中的Activity正在与用户进行交互;进程服务被Activity调用,而且这个Activity正在与用户进行交互;进程服务正在执行声明周期中的回调函数,如onCreate()、onStart()或onDestroy();进程的BroadcastReceiver正在执行onReceive()函数;通常,前台进程不会被系统终止,除非系统资源极度紧张。在这种情况下,系统会首先尝试终止低优先级的进程来释放资源,以保证前台进程的正常运行。7.2进程和优先级(2)可见进程可见进程指的是部分程序界面能够被用户看到,但不在前台与用户交互,不响应界面事件的进程。例如,当一个新启动的Android程序部分遮挡了原有程序界面时,原有程序的Activity会从前台进程变为可见进程。另外,如果一个进程包含服务,且该服务正在被用户可见的Activity调用,这个进程也会被视为可见进程。一般来说,Android系统中会存在少量的可见进程,只有在资源紧张时,系统才会优先清除可见进程,以保证前台进程的资源需求。7.2进程和优先级(3)服务进程服务进程是指包含已启动服务的进程。服务没有用户界面,不直接与用户交互,但能够在后台长期运行,提供重要的功能,如播放MP3或从网络下载数据。除非系统资源无法满足前台进程或可见进程的需求,否则Android系统不会强行终止服务进程。7.2进程和优先级(4)后台进程后台进程指的是不包含任何已启动服务,且没有用户可见的Activity的进程。例如,一个仅包含Activity的进程,当用户启动其他应用程序并遮挡住该进程的界面时,当前进程的Activity将成为后台进程。一般来说,Android系统中会存在大量的后台进程,系统会优先清除那些较长时间未被使用的后台进程,以释放系统资源。7.2进程和优先级(5)空进程空进程是不包含任何活跃组件的进程。例如,一个仅包含Activity的进程,当用户关闭Activity后,该进程变为空进程。空进程通常会在系统资源紧张时被首先清除。然而,为了提高系统的响应速度,Android系统可能会在内存充足时保留空进程,以便在用户重新启动该程序时能够更快地恢复。在Android中,进程的优先级取决于进程中所有组件中的优先级最高部分。例如,如果一个进程同时包含可见的Activity和已启动的服务,则该进程的优先级将是可见进程,而不是服务进程,因为Activity的优先级更高。7.3Activity生命周期7.3.1四种状态Activity生命周期指Activity从启动到销毁的过程,在这个过程中,Activity一般表现为四种状态,分别是活动状态、暂停状态、停止状态和非活动状态。活动状态,当Activity在用户界面中处于最上层,完全能被用户看到,能够与用户进行交互,则这个Activity处于活动状态。暂停状态,当Activity在界面上被部分遮挡,该Activity不再处于用户界面的最上层,且不能够与用户进行交互,则这个Activity处于暂停状态。停止状态,当Activity在界面上完全不能被用户看到,也就是说这个Activity被其它Activity全部遮挡,则这个Activity处于停止状态。非活动状态,指的是在以上三种状态(活动状态、暂停状态和停止状态)之外的其他状态7.3Activity生命周期7.3.1四种状态Activity处于活动状态时,Activity位于界面最上层,并与用户进行交互,Android系统会优先保证处于活动状态的Activity的资源需求。在系统资源紧张时,Android系统可能会终止处于其它状态的Activity,以保证活动状态的Activity正常运行;如果用户启动了一个新的Activity,部分遮挡了当前Activity,或者新Activity是半透明的,则当前Activity会转换为暂停状态。在这种状态下,Android系统通常不会终止暂停状态的Activity,除非为活动状态的Activity释放资源时才会清除它;如果新启动的Activity完全遮挡了当前Activity,则当前Activity会转变为停止状态。停止状态的Activity会在资源紧张时优先被终止;当活动状态的Activity被用户关闭,或者暂停状态或停止状态的Activity被系统终止时,Activity会进入非活动状态7.3Activity生命周期7.3.2Activity栈Activity栈保存了已经启动且没有终止的所有Activity,并遵循“后进先出”的规则。栈顶的Activity处于活动状态,除栈顶以外的其它Activity处于暂停状态或停止状态,而被终止的Activity或已经出栈的Activity则不在栈内Activity的状态与其在Activity栈中的位置密切相关。Android系统在资源不足时,会依据Activity栈的位置和状态来选择哪些Activity可以被终止。通常,系统会优先选择终止那些处于停止状态且靠近栈底的Activity,因为这些Activity不再对用户可见,并且被重新调用的机会较小7.3Activity生命周期7.3.3回调函数随着用户在界面上的操作以及Android系统对资源的动态管理,Activity在Activity栈中的位置和状态不断变化。这些变化对应着Activity生命周期中的不同状态,Android系统会根据状态的变化调用相应的生命周期回调函数。开发人员可以在这些方法中添加代码,以便在Activity状态变化时执行相应的操作,完成特定任务。Activity中共有七个生命周期回调函数,分别是onCreate()、onStart()、onResume()、onPause()、onStop()、onRestart()和onDestroy()7.3Activity生命周期7.3.3回调函数这些生命周期回调函数的使用场景如下:onCreate():Activity被创建时调用,通常用于初始化界面、绑定控件、设置监听器等。onStart():Activity即将变得可见时调用。此时Activity已被加载到内存中,但用户还不可交互。onResume():Activity将与用户进行交互时调用。此时Activity处于前台,用户可以与其交互。onPause():Activity失去焦点,但依然可见时调用。此时可以保存数据或释放资源(例如,暂停音乐或动画)。onStop():Activity不再可见时调用。例如,另一个Activity启动并覆盖当前Activity,或者当前Activity被系统暂停时。onRestart():Activity从停止状态重新进入前台时调用。通常在onStop()后调用。onDestroy():Activity销毁前调用。此时用于清理资源7.3Activity生命周期7.3.3回调函数在下面的代码中,分别实现了两个生命周期函数:onCreate()和onStart()。其中,super.onCreate(savedInstanceState)和super.onStart()都是调用了父类的初始化函数1
overridefunonCreate(savedInstanceState:Bundle?){2
super.onCreate(savedInstanceState)3
}4
5
overridefunonStart(){6
super.onStart()7
}在Android中,调用父类的生命周期方法是为了保证父类的功能正常执行。父类管理Activity的生命周期,执行重要的操作,如界面布局的设置和生命周期管理。如果不调用父类的方法,这些操作将无法执行,可能导致应用异常或不稳定。7.3Activity生命周期7.3.3回调函数下面给出全部Activity生命周期回调函数的代码:16
}17
18
//在活动生命周期结束时被调用,用来保存持久的数据或释放占用的资源19
overridefunonPause(){20
super.onPause()21
}22
23
//在可视生命周期结束时被调用,用来释放占用的资源24
overridefunonStop(){25
super.onStop()26
}27
28
//在完全生命周期结束时被调用,释放资源,包括线程、数据连接等29
overridefunonDestroy(){30
super.onDestroy()31
}1
//被创建时调用,通常用于初始化界面、绑定控件、设置监听器等。2
overridefunonCreate(savedInstanceState:Bundle?){3
super.onCreate(savedInstanceState)4
}5
//可视生命周期开始时被调用,对用户界面进行必要的更改6
overridefunonStart(){7
super.onStart()8
}9
//在活动生命周期开始时被调用,恢复被onPause()停止的用于界面更新的资源10
overridefunonResume(){11
super.onResume()12
}13
//在重新进入可视生命周期前被调用,载入界面所需要的更改信息14
overridefunonRestart(){15
super.onRestart()7.3Activity生命周期7.3.4状态保存和恢复除了Activity生命周期回调函数以外,还有还有两个经常会被使用的函数:onRestoreInstanceState()和onSaveInstanceState()。用于保存和恢复Activity的界面临时信息,如用户在界面中输入的数据或选择的内容等。onSaveInstanceState()用于保存临时状态,如用户输入的数据、滚动位置等。通常在Activity暂停或停止时调用(例如屏幕旋转或切换到另一个Activity时)。它不会在Activity被显式关闭(调用finish())时被调用,而是由系统在Activity被销毁前调用,特别是当Activity被系统因内存管理等原因销毁时。onRestoreInstanceState()用于恢复临时状态,即从onSaveInstanceState()中保存的数据。它会在Activity恢复到前台时被调用,通常发生在onStart()之后,恢复用户输入的数据和其他界面状态7.3Activity生命周期7.3.4状态保存和恢复举个例子说明这两个函数是如何被调用的。如用户启动ActivityA,然后直接又启动ActivityB,这时系统需要停止ActivityA,则会调用ActivityA的onSaveInstanceState()来保存ActivityA的界面临时信息。当用户主动关闭ActivityB时,ActivityB的onSaveInstanceState()不会被调用,因为是用户主动关闭ActivityB而不是系统暂停的,所以当ActivityA重新显示在屏幕上后,ActivityA调用onRestoreInstanceState()用以恢复之前保存的ActivityA的状态信息7.3Activity生命周期7.3.4状态保存和恢复在下面的代码中,分别实现了onRestoreInstanceState()和onSaveInstanceState()1
//在onStart()后被调用,用于恢复onSaveInstanceState()保存的用户界面信息2
overridefunonRestoreInstanceState(savedInstanceState:Bundle){3
super.onRestoreInstanceState(savedInstanceState)4
//恢复保存的数据5
valsavedValue=savedInstanceState.getString("key")6
}7
8
//在onPause()后被调用,保存界面临时信息9
overridefunonSaveInstanceState(savedInstanceState:Bundle){10
super.onSaveInstanceState(savedInstanceState)11
//保存一些临时数据12
savedInstanceState.putString("key","value")13
}在onSaveInstanceState()方法中,savedInstanceState参数的类型是Bundle,表示它是一个Bundle对象。Bundle本质上是一个键值对集合,可以存储基本数据类型(如字符串、整数、布尔值等)以及它们的组合。Bundle是可以保存不同数据格式的对象,onSaveInstanceState()会将界面状态数据保存在Bundle中,并在onRestoreInstanceState()或onCreate()中恢复这些数据。onSaveInstanceState()主要用于保存界面状态,它的作用是确保Activity在被系统销毁后能够恢复到用户上次离开时的状态。7.3Activity生命周期7.3.5执行顺序在Activity的生命周期中,调用会遵循描述的调用顺序使用者在onCreate()中初始化Activity所能使用的全局资源和状态,并在onDestroy()中释放这些资源。7.3Activity生命周期7.3.5执行顺序onStart()一般用来初始化或启动与更新界面相关的资源。onStop()一般用来暂停或停止一切与更新用户界面相关的线程、计时器或Service等,因为在调用onStop()后,Activity对用户不再可见,更新用户界面也就没有任何实际意义。onRestart()函数在onSart()前被调用,用来在Activity从不可见变为可见的过程中,进行一些特定的处理过程。因为Activity不断从可见变为不可见,再从不可见变为可见,所以onStart()和onStop()会被多次调用。另外,onStart()和onStop()也经常被用来注册和注销BroadcastReceiver,例如使用者可以在onStart()中注册一个BroadcastReceiver,用来监视某些重要的广播消息,并使用这些消息更新用户界面中的相关内容,并可以在onStop()中注销BroadcastReceiver。
7.3Activity生命周期7.3.5执行顺序很多开发者在使用onPause()和onSaveInstanceState()时可能会感到困惑,因为它们都可以用来保存用户输入的数据。但这两个方法的作用有所不同:onPause()主要用于保存持久化数据,如用户输入的文本、选项等,这些数据通常会被存储在文件系统、数据库或SharedPreferences中。onPause()还可以用来暂停正在进行的任务,例如视频播放或计时器。onSaveInstanceState()主要用于保存临时状态数据,例如当前界面的状态、滚动位置、用户输入的字段等,这些数据通常会保存在Bundle中。onSaveInstanceState()旨在应对
系统资源不足或Activity被临时销毁(如屏幕旋转、切换应用等)时恢复界面状态7.4组件生命周期7.4.1ServiceService是Android中用于执行长期运行操作的组件,它的生命周期与Activity不同。Service可以在后台执行任务,甚至在用户界面不可见时依然运行。Service的生命周期回调函数:onCreate():Service被创建时调用。通常用于初始化Service并设置资源。onStartCommand():当startService()启动Service时调用。每次调用都会启动一次Service。onBind():当其他组件通过bindService()绑定Service时调用。它允许与Service进行通信。onUnbind():当所有绑定的组件都解除绑定时调用。可以释放资源。onDestroy():Service销毁时调用。通常用于清理资源,停止后台任务等。7.4组件生命周期7.4.2BroadcastReceiverBroadcastReceiver用于接收并处理广播消息,它生命周期仅限于onReceive()的执行。BroadcastReceiver的生命周期回调函数:onReceive():每当接收到广播消息时调用。处理广播消息时,onReceive()方法会立即执行。它非常短暂,通常只用于处理广播并启动其他组件7.4组件生命周期7.4.3ContentProviderContentProvider用于在不同应用之间共享数据,通过在AndroidManifest.xml中注册,并在其他应用或组件访问时启动的。它的生命周期通常由其注册和访问时决定。ContentProvider的生命周期回调函数:onCreate():ContentProvider创建时调用,用于初始化必要的资源和配置。query():用于查询数据,返回数据的游标(Cursor)。insert():用于插入数据到ContentProvider中。update():用于更新ContentProvider中的数据。delete():用于删除ContentProvider中的数据。getType():返回指定URI的MIME类型。7.5ActivityLifeCycle示例7.5.1UI代码为了能够更好的理解Activity回调函数的调用顺序,下面以ActivityLifeCycle示例来进行说明。7.5ActivityLifeCycle示例7.5.1UI代码UI核心代码:1
setContent{2
Column{3
Text(text="")4
Text(text="HelloActivityLifeCycle")5
Button(onClick={6
finish()7
}){8
Text("结束程序")9
}10
}11
}这段代码通过JetpackCompose定义了一个包含两个文本(Text)和一个按钮(Button)的界面,使用Column布局将所有UI控件垂直排布。点击按钮时,会调用finish()方法结束当前Activity,从而关闭当前应用7.5ActivityLifeCycle示例7.5.2日志代码通过点击左下方的“小猫脸”按钮,打开Logcat的日志信息,如图所示:7.5ActivityLifeCycle示例7.5.2日志代码LogCat的日志信息中,五个字母[V]、[D]、[I]、[W]和[E],表示五种不同类型的日志信息,分别是详细(Verbose)信息、调试(Debug)信息、通告(Info)信息、警告(Warn)和错误(Error)信息。不同类型日志信息的级别是不相同的,级别最高的错误信息,其次是警告信息,然后是通知信息和调试信息,级别最低的是详细信息。在Android程序调试过程中,使用Log.v()、Log.d()、Log.i()、Log.w()和Log.e()五个函数在程序中设置“日志点”。每当程序运行到“日志点”时,应用程序的日志信息便被发送到LogCat中,使用者可以根据“日志点”信息是否与预期的内容一致,判断程序是否存在错误1
valTAG="LIFTCYCLE"2
Log.v(TAG,"打印这条信息Verbose");3
Log.d(TAG,"打印这条信息Debug");4
Log.i(TAG,"打印这条信息Info");5
Log.w(TAG,"打印这条信息Warn");6
Log.e(TAG,"打印这条信息Error");7.5ActivityLifeCycle示例7.5.2日志代码这里的TAG是一个表示标签的字符串,用于帮助开发者标记和筛选不同类型的日志信息。设置了标签后,每次的日志信息都会有这个标签。这样就可以在Logcat右上角的搜索栏中输入标签“LIFTCYCLE”,日志信息中标签为“LIFTCYCLE”的条目会被显示出来,其他不相关的条目会被隐藏,如图所示:搜索栏还支持“键值对”组成的搜索条件进行查询,例如搜索包名为com.example.abc的日志数据,就可以在搜索栏中输入package:com.example.abc7.5ActivityLifeCycle示例7.5.3生命周期代码ActivityLifeCycle示例的核心代码,首先做了包声明(packagedeclaration),代码是“packagecom.example.activitylifecycle”,指定当前文件所在的包(package)。包的作用是对类、接口、函数等进行逻辑分组,有助于组织代码,并避免类名冲突。import关键字用于引入外部类、接口、函数或库,使得在当前文件中能够使用这些类或库中的功能,而不需要使用完整的类名路径7.5ActivityLifeCycle示例7.5.3生命周期代码ActivityLifeCycle示例的核心代码:34
overridefunonRestoreInstanceState(savedInstanceState:Bundle){35
super.onRestoreInstanceState(savedInstanceState)36
Log.i(TAG,"(3)onRestoreInstanceState()")37
}38
39
overridefunonResume(){40
super.onResume()41
Log.i(TAG,"(4)onResume()")42
}43
44
overridefunonSaveInstanceState(savedInstanceState:Bundle){45
super.onSaveInstanceState(savedInstanceState)46
Log.i(TAG,"(5)onSaveInstanceState()")47
}48
49
overridefunonRestart(){50
super.onRestart()51
Log.i(TAG,"(6)onRestart()")52
}53
54
overridefunonPause(){55
super.onPause()56
Log.i(TAG,"(7)onPause()")57
}58
59
overridefunonStop(){60
super.onStop()61
Log.i(TAG,"(8)onStop()")62
}63
64
overridefunonDestroy(){65
super.onDestroy()66
Log.i(TAG,"(9)onDestroy()")67
}68
}1
packagecom.example.activitylifecycle2
3
importandroid.os.Bundle4
importandroid.util.Log5
importandroidx.activity.ComponentActivity6
importpose.setContent7
importpose.foundation.layout.Column8
importpose.material3.Button9
importpose.material3.Text10
11
ClassMainActivity:ComponentActivity(){12
privatevalTAG="LIFTCYCLE"13
overridefunonCreate(savedInstanceState:Bundle?){14
super.onCreate(savedInstanceState)15
Log.i(TAG,"(1)onCreate()")16
setContent{17
Column{18
Text(text="")19
Text(text="HelloActivityLifeCycle")20
Button(onClick={21
finish()22
}){23
Text("结束程序")24
}25
}26
}27
}28
29
overridefunonStart(){30
super.onStart()31
Log.i(TAG,"(2)onStart()")32
}33
7.5ActivityLifeCycle示例7.5.3生命周期代码(1)完全生命周期为了观察Activity从启动到关闭所调用的生命周期回调函数的顺序,首先正常启动ActivityLifeCycle,然后点击用按钮“结束程序”按钮关闭程序。LogCat的输出结果如图所示:完全生命周期的函数调用顺序如下:(1)onCreate→(2)onStart→(4)onResume→(7)onPause→(8)onStop→(9)onDestroy当Activity被创建时,系统首先调用onCreate()函数,然调用onStart(),表示Activity已经变得对用户可见,但尚未与用户交互。之后调用onResume(),表示Activity已经获得了焦点,可以与用户交互。这时,Activity进入前台,用户可以正常与应用进行交互。用户点击“结束程序”按钮,会导致Activity关闭,系统会相继调用onPause()、onStop()和onDestroy(),释放资源并销毁进程。因为Activity关闭后,除非用户重新启动应用程序,否则这个Activity不会在出现在屏幕上,因此系统直接调用onDestroy()销毁了进程,且没有调用onSaveInstanceState()函数来保存Acitivity状态7.5ActivityLifeCycle示例7.5.3生命周期代码(2)可视生命周期在Activity启动后,如果启动其它的程序,或者按Home键,则会让原有Activity会进入停止状态。如果将新启动的程序关闭,或者重新打开这个Activity,则原有Activity从停止状态恢复到活动状态为了能够分析上述状态转换过程中的函数调用顺,首先正常启动ActivityLifeCycle,然后点击Home键显示Android桌面,让ActivityLifeCycle进入后台,如图所示7.5ActivityLifeCycle示例7.5.3生命周期代码(2)可视生命周期然后再从Android桌面图标中找到ActivityLifeCycle的启动图标,点击图片再次打开ActivityLifeCycle,如图所示:在这样操作后,LogCat的输出结果如图所示:7.5ActivityLifeCycle示例7.5.3生命周期代码(2)可视生命周期可视生命周期的函数调用顺序如下:(1)onCreate→(2)onStart→(4)onResume→(7)onPause→(8)onStop→(5)onSaveInstanceState→(6)onRestart→(2)onStart→(4)onResume。Activity启动时的函数调用顺序仍为(1)→(2)→(4),当点击Home键让程序进入后台后,系统首先调用onPause()和onStop(),然后调用onSaveInstanceState()函数保存Activity状态。在重新打开ActivityLifeCycle程序后,系统调用onRestart()更新信息,然后调用onStart()和onResume()重新显示Activity,并接受用户交互。Android系统虽然调用了onSaveInstanceState(),允许用户保存Activity的状态信息,但因为Activity并没有被销毁,所以没有必要调用onRestoreInstanceState(),让用户恢复保存的Activity状态7.5ActivityLifeCycle示例7.5.3生命周期代码(3)调用onRestoreInstanceState()要让Activity调用onRestoreInstanceState()方法,通常是因为Activity的状态需要恢复。这通常发生在以下几种情况:屏幕旋转:当设备方向变化时,Activity会被销毁并重新创建,系统会自动调用onRestoreInstanceState()来恢复之前保存的状态。内存不足:当系统为了回收内存而销毁Activity时,恢复Activity时会调用onRestoreInstanceState()。Activity被覆盖和重新恢复:如果Activity被其他Activity替换或进入后台,回到前台时也会调用onRestoreInstanceState()7.5ActivityLifeCycle示例7.5.3生命周期代码(3)调用onRestoreInstanceState()屏幕旋转是比较简单的实现调用onRestoreInstanceState()的方法,因此这里采用这个方法。如图所示,点击模拟器的“旋转屏幕”按钮,让ActivityLifeCycle示例从竖屏变为横屏。在获取函数调用顺序前,先修改一下代码,在onSaveInstanceState()中保存一个数据,然后在onRestoreInstanceState()恢复这个数据7.5ActivityLifeCycle示例7.5.3生命周期代码(3)调用onRestoreInstanceState()这段代码中,putString(KEY,value)是Bundle类提供的方法,用于将字符串类型的值
存储在Bundle中。KEY是保存该值的键,value是需要保存的字符串数据。在代码Log.i(TAG,"保存数据,key:$KEY,value:$value")中,其中的key:$KEY,value:$value是一个字符串模板,它将KEY和value的值动态地插入到日志消息中1
classMainActivity:ComponentActivity(){2
3
privatevalTAG="LIFTCYCLE"4
privatevalKEY="MyKey"5
6
overridefunonRestoreInstanceState(savedInstanceState:Bundle){7
super.onRestoreInstanceState(savedInstanceState)8
Log.i(TAG,"(3)onRestoreInstanceState()")9
//恢复保存的数据10
valsavedValue=savedInstanceState.getString(KEY)11
Log.i(TAG,"恢复数据,key:$KEY,value:$savedValue")12
}13
14
overridefunonSaveInstanceState(savedInstanceState:Bundle){15
super.onSaveInstanceState(savedInstanceState)16
Log.i(TAG,"(5)onSaveInstanceState()")17
//保存临时数据18
valvalue="这里是保存的数据"19
savedInstanceState.putString(KEY,value)20
Log.i(TAG,"保存数据,key:$KEY,value:$value")21
}22
}7.5ActivityLifeCycle示例7.5.3生命周期代码(3)调用onRestoreInstanceState()这时可以先清空Logcat,然后重新启动ActivityLifeCycle程序。点击“旋转屏幕”按钮让手机模拟器的屏幕产生旋转,这时候的Logcat如图所示函数调用顺序如下:(1)onCreate→(2)onStart→(4)onResume→(7)onPause→(8)onStop→(5)onSaveInstanceState→(9)onDestroy→(1)onCreate→(2)onStart→(3)onRestoreInstanceState→(4)onResume这组生命周期的回调方法反映了Activity的创建、可见、暂停、销毁和重建过程,适用于很多典型的应用场景,如屏幕旋转、配置变化等,需要开发者根据这些调用顺序来处理资源管理和状态保存/恢复习题1.简述Android系统前台进程、可见进程、服务进程、后台进程和空进程的优先级排序原因。2.简述Android系统的四种基本组件Activity、Service、BroadcaseReceiver和ContentProvider的用途。3.简述Activity生命周期回调函数的作用和调用顺序。THANKS谢谢观看Android课程第8章组件通信与广播消息任课教师:某某某学习目标AIMS了解使用Intent进行组件通信的原理01020304掌握使用Intent启动Activity的方法掌握获取Activity返回值的方法了解Intent过滤器的原理与匹配机制05掌握发送和接收广播消息的方法
Intent简介
Intent是一种轻量级的消息传递机制是一个动作的完整描述,包含了动作的产生组件、接收组件和传递的数据信息用于组件之间数据交换Activity、Service和BroadcastReceiver的数据交互启动Activity和Service发送广播消息应用程序广播消息系统广播消息手机的信号变化电池的电量过低8.1
Intent简介8.1.1启动Activity应用程序一般都有多个Activity,Intent可以实现不同Activity之间的切换和数据传递启动Activity方式显式启动必须在Intent中指明启动的Activity所在的类隐式启动根据Intent的动作和数据来决定启动哪一个Activity选择权有Android系统和最终用户来决定8.1
Intent简介8.1.1启动Activity显式启动创建一个Intent指定当前的应用程序上下文,以及要启动的Activity把创建好的Intent作为参数传递给startActivity()方法valintent=Intent(Intent.ACTION_VIEW,this,NewActivity::class.java)startActivity(intent)8.1
Intent简介8.1.1启动Activity显式启动用IntentDemo示例说明如何使用Intent启动新的Activity示例中有两个Activity:IntentDemoActivity和NewActivity。程序默认启动的Activity是IntentDemo在点击“启动Activity”按钮后,启动的NewActivity8.1
Intent简介8.1.1启动Activity显式启动务必在AndroidManifest.xml文件中注册这两个ActivityAndroidManifest.xml文件代码如下:1<manifestxmlns:android="/apk/res/android"2package="edu.hrbeu.IntentDemo">34<application5android:icon="@drawable/ic_launcher"6android:label="@string/app_name">78<activity9android:name=".IntentDemoActivity"10android:exported="true">11<intent-filter>12<actionandroid:name="ent.action.MAIN"/>13<categoryandroid:name="ent.category.LAUNCHER"/>14</intent-filter>15</activity>1617<activity18android:name=".NewActivity"19android:exported="false">20</activity>21</application></manifest>8.1
Intent简介8.1.1启动Activity显式启动在IntentDemoActivity.kt文件中,包含了使用Intent启动Activity的核心代码:valintent=Intent(this,NewActivity::class.java)startActivity(intent);Intent构造函数的第1个参数是应用程序上下文,在这里就是IntentDemoActivity第2个参数是接收Intent的目标组件,这里使用的是显式启动方式,直接指明了需要启动的Activity8.1Intent简介8.1.1启动Activity隐式启动不需要指明需要启动哪一个Activity,而由Android系统和用户来决定具体启动哪个Activity有利于降低组件之间的耦合度隐式启动的原理:选择隐式启动Activity,Android系统会在程序运行时解析Intent,并根据一定的规则对Intent和Activity进行匹配,使Intent上的动作、数据与Activity完全吻合匹配的组件可以是程序本身的Activity,也可以是Android系统内置的Activity,还可以是第三方应用程序提供的Activity这种方式强调了Android组件的可复用性8.1Intent简介8.1.1启动Activity隐式启动使用Intent隐式启动浏览器,查看指定的网页内容可将“浏览动作”和“Web地址”作为参数传递给IntentAndroid系统则通过匹配动作和数据格式,找到最适合于此动作和数据格式的组件在匹配Intent时,根据动作Intent.ACTION_VIEW得知需要启动具备浏览功能的Activity,但具体是浏览电话号码还是浏览网页,还需要根据URI的数据类型来做最后判断因为数据提供的是Web地址"",所以最终可以判定Intent需要启动具有网页浏览功能的Activity在缺省情况下,Android系统会调用内置的Web浏览器1
valintent=Intent(Intent.ACTION_VIEW,Uri.parse(""))2
startActivity(intent)8.1
Intent简介8.1.1启动ActivityAndroid系统支持的“动作字符串常量”8.1动作说明ACTION_ANSWER打开接听电话的Activity,默认为Android内置的拨号界面ACTION_CALL打开拨号盘界面并拨打电话,使用Uri中的数字部分作为电话号码ACTION_DELETE打开一个Activity,对所提供的数据进行删除操作ACTION_DIAL打开内置拨号界面,显示Uri中提供的电话号码ACTION_EDIT打开一个Activity,对所提供的数据进行编辑操作ACTION_INSERT打开一个Activity,在提供数据的当前位置插入新项ACTION_PICK启动一个子Activity,从提供的数据列表中选取一项ACTION_SEARCH启动一个Activity,执行搜索动作ACTION_SENDTO启动一个Activity,向数据提供的联系人发送信息ACTION_SEND启动一个可以发送数据的Activity,共享数据,例如通过短信、邮件、社交应用发送文本、图片等ACTION_VIEW最常用的动作,对以Uri方式传送的数据,根据Uri协议部分以最佳方式启动相应的Activity进行处理。对于http:address将打开浏览器查看;对于tel:address将打开拨号界面并呼叫指定的电话号码ACTION_WEB_SEARCH打开一个Activity,对提供的数据进行Web搜索ACTION_CHOOSER显示应用选择器,让用户选择一个应用来处理
IntentACTION_GET_CONTENT允许用户选择某种类型的数据返回(如文件选择器)ACTION_MAIN启动应用主界面,通常用于
Launcher启动ActivityACTION_BOOT_COMPLETED设备启动完成的广播(需要声明权限)ACTION_BATTERY_LOW电池电量低时的广播通知ACTION_CAMERA_BUTTON用户按下相机按钮时的广播ACTION_SCREEN_ON屏幕打开时的广播ACTION_SCREEN_OFF屏幕关闭时的广播
Intent简介8.1.1启动Activity隐式启动WebViewIntentDemo示例说明了如何隐式启动Activity1.
valintent=Intent(Intent.ACTION_VIEW,Uri.parse(urlString))2
.startActivity(intent)8.1Intent简介8.1.2Activity数据传递如何将“子Activity”的数据返回给“父Activity”?使用Sub-Activity的方式去启动子ActivityActivityCommunication示例
ActivityCommunication最下面的输入框是传递给SubActivity的数据,点击“启动SubActivity”按钮后,会启动SubActivity。SubActivity提供了一个输入框,以及“接受”和“撤销”两个按钮。如果在输入框中输入信息后点击“接受”按钮,会把输入框中的信息传递给其父Activity,并在父Activity的界面上显示。而如果用户点击“撤销”按钮,则程序不会向父Activity传递任何信息。8.1Intent简介8.1.2Activity数据传递对ActivityCommunication而言,ActivityCommunication是如何启动SubActivity并获取返回结果代码的呢?对SubActivity而言,SubActivity是如何解析,接受,撤销数据呢?8.1Intent简介8.1.2Activity数据传递ActivityCommunication启动SubActivity并获取返回结果代码1.vartextbyremember{mutableStateOf(“”)}2.vallauncherSubActivity=rememberLauncherForActivityResult(3.contract=ActivityResultContracts.StartActivityForResult()4.){result->5.if(result.resultCode==RESULT_OK){6.valdata:String?=result.data?.dataString7.text=data?:“NoData”8.}9.}
rememberLauncherForActivityResult的作用是在JetpackCompose中注册一个ActivityResultLauncher,用于启动Activity并接收返回结果。contract指定了启动Activity并获取返回结果的行为。ActivityResultContracts.StartActivityForResult()是系统预定义的contract,用于:启动一个Activity,同时获取该Activity的返回值(Intent)8.1Intent简介8.1.2Activity数据传递ActivityCommunication启动SubActivity并获取返回结果代码1valcontext=LocalContext.current2vartextbyremember{mutableStateOf("")}3varinputTextbyremember{mutableStateOf("")}4valintent=Intent(context,SubActivity::class.java)5intent.putExtra("data",inputText)6launcherSubActivity.launch(intent)第1行代码LocalContext.current是JetpackCompose提供的API,用于获取当前上下文(Context)。第4行创建一个Intent,用于从当前Activity跳转到SubActivity。第5行通过Intent.putExtra("key",value)传递数据,将用户输入的文本数据inputText传递到SubActivity中。第6行代码使用rememberLauncherForActivityResult启动SubActivity并等待返回结果。之所以不用startActivity(intent),是因为这样不会返回数据。8.1Intent简介8.1.2Activity数据传递SubActivity中解析数据的代码1valcontext=LocalContext.currentasComponentActivity2ent.getStringExtra("data")?:""8.1第1行代码asComponentActivity,强制转换Context为ComponentActivity,因为LocalContext.current可能是ApplicationContext,但intent只存在于Activity上下文中。第2行代码ent获取了当前Activity启动时的Intent,.getStringExtra("data")尝试从Intent中获取名为"data"的字符串数据,如果"data"不存在,返回空字符串。Intent简介8.1.2Activity数据传递SubActivity中,“接受”按钮的代码1Button(onClick={2valresultIntent=Intent()3resultIntent.data=Uri.parse(inputText)4context.setResult(Activity.RESULT_OK,resultIntent)5context.finish()6}){7Text("接受")8}8.1第2行代码创建一个空的Intent,用于存放返回给上一个Activity的数据。第3行代码将inputText(字符串)解析为Uri格式,再将Uri作为返回数据存入Intent。第4行代码setResult()用于设置当前Activity的返回结果,其中Activity.RESULT_OK表示操作成功(系统内置常量),resultIntent是要返回的数据。第5行代码关闭当前Activity,返回上一个Activity。Intent简介8.1.2Activity数据传递SubActivity中,“撤销”按钮的代码1Button(onClick={2context.setResult(Activity.RESULT_CANCELED)3context.finish()4})5{6Text("撤销")7}8.1这里的代码不同指出在于第2行,Activity.RESULT_CANCELED表示操作撤销。
Intent过滤器Intent解析Android系统一定存在一种匹配机制,使Android系统能够根据Intent中的数据信息,找到需要启动的组件这种匹配机制是依靠Android系统中的Intent过滤器(IntentFilter)来实现的648.2Intent过滤器Intent解析AndroidManifest.xml文件代码:<activityandroid:name=".NewActivity"android:exported="true">
<intent-filter><actionandroid:name="ent.action.VIEW"/><categoryandroid:name="ent.category.DEFAULT"/><dataandroid:scheme="schemodemo"android:host="edu.hrbeu"/></intent-filter></activity>valintent=Intent(Intent.ACTION_VIEW,Uri.parse("schemodemo://edu.hrbeu/path"))context.startActivity(intent)Intent启动Activity代码:8.2Intent过滤器Intent解析Intent过滤器是一种根据Intent中的动作(Action)、类别(Categorie)和数据(Data)等内容,对适合接收该Intent的组件进行匹配和筛选的机制可以匹配数据类型、路径和协议,还可以确定多个匹配项顺序的优先级(Priority)注册Intent过滤器的组件ActivityServiceBroadcastReceiver<intent-filter>节点中<action>标签:Intent过滤器的“动作”<category>标签:Intent过滤器的“类别”<data>标签:Intent过滤器的“数据”8.2<activityandroid:name=".NewActivity"android:exported="true"><intent-filter><actionandroid:name="ent.action.VIEW"/><categoryandroid:name="ent.category.DEFAULT"/><dataandroid:scheme="schemodemo"android:host="edu.hrbeu"/></intent-filter></activity>Intent过滤器<intent-filter>节点支持的标签和属性说明:8.2标签属性说明<action>android:name指定组件可响应的动作,通常是标准的
IntentAction(如ent.action.VIEW)或自定义的字符串(建议使用完整类名)<category>android:category指定组件如何匹配Intent请求,常见值包括ent.category.DEFAULT(默认类别)<data>
android:host指定
URI中的主机名(例如)
android:mimetype指定组件能够处理的数据类型(如
image/*表示所有图片类型)
android:path指定
URI中的完整路径(如/user/profile)
android:port指定
URI的端口号(如8080)
android:scheme指定所需的特定协议(如
http、https、tel)
android:pathPattern指定
URI路径的匹配模式,可以使用*和.作为通配符(如/user/.*)
android:pathPrefix指定
URI路径的前缀,匹配路径的开头部分(如/user/匹配/user/123)<intent-filter>android:priority定义
Intent过滤器的优先级,数值越高,匹配时的优先级越高
android:label指定过滤器的标签,用于调试和日志
android:icon指定过滤器的图标资源
android:autoVerify启用
Android的自动验证机制,确保URI解析到正确的App(用于深度链接验证)Intent过滤器<category>标签<category>标签用来指定Intent过滤器的服务方式Android系统提供的常用类别:8.2值说明DEFAULT使Activity可以通过startActivity(Intent)启动(如果Intent没有category.DEFAULT,可能无法匹配Intent-Filter)。BROWSABLE
允许
Activity被Web浏览器或外部应用打开,适用于深度链接(DeepLink)LAUNCHER使Activity显示在应用启动器(Launcher)中,作为应用入口(通常是MainActivity)HOME使
Activity作为系统主界面(Launcher),如桌面应用(类似PixelLauncher)Intent过滤器<category>标签Android系统提供的特殊用途类别:8.2值说明APP_BROWSER指定Activity是一个Web浏览器,例如Chrome、FirefoxAPP_CALCULATOR指定Activity是计算器应用APP_CALENDAR指定Activity是日历应用APP_CONTACTS指定Activity是联系人应用APP_EMAIL指定Activity是电子邮件应用A
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 春季消防安全检查工作总结
- 2027届平塘县数学三上期末达标检测试题含解析
- 素土分层回填夯实施工工艺
- 部编版八下历史《期末冲刺背诵秘笈》
- 《数字展会VR展示服务规范》
- 麻醉药品和精神药品培训考核试题(附答案)
- 输血科三基知识考试试题及答案
- 2026年物业服务企业财务经理工作计划
- 2026年静脉输血培训试题及答案
- 配送企业铣工日常检查安全操作规程
- 提高护理SBAR沟通模式执行率FOCUS-PDCA获奖案例成果汇报
- 安全阀拆装培训课件
- 纪检监察机关证据课件
- 河南省养老类建筑消防设计技术要点2025
- 2025年江苏省各市、县(区)三新供电服务招聘考试(计算机类)历年参考题库含答案详解(5卷)
- 血透导管相关血流感染
- (高清版)DG∕TJ 08-2384-2022 建筑工程固定脚手架及支撑架技术标准
- 吞咽功能障碍护理常规
- 人教版九年级数学上册《实际问题与一元二次方程》课件
- 售后服务方案及承诺详细的售后服务方案及承诺
- 承包商安全教育培训课件
评论
0/150
提交评论