Activity

了解Activity的生命周期 任务栈 切换动画 传值

(一)Activity概述+配置

理解为一个舞台,表演由fragment来扮演
一个Activity就是一个独立的界面。
所有的Activity都必须在Manifest文件中注册(首相首先自己清楚有哪些界面)

在清单文件(manifests -> AndroidManifest.xml)中

exported:指示给定的应用程序组件是否可用于其他应用程序
如果为false,则只能由具有相同用途的应用程序访问(这通常意味着只能通过自己包中的代码)。
如果为true,它可以被外部实体调用,尽管哪些实体可以这样做可能会通过权限来控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<manifest ... >
<application >

<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode=""> <!--改成true外部也可以访问-->
<intent-filter>
<!-- 别人通过什么动作找到我-->
<action android:name="android.intent.action.MAIN" />
<!--属于什么类别-->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
...
</manifest >

(二)Intent意图

finish() //关闭当前界面,返回上一界面

(1)显⽰意图

app内部跳转,在自己应用内做跳转,明确指定跳转⻚⾯
startActivity(Intent(this,HomeActivity::class.java))

1
2
3
4
5
6
7
8
//点击主界面跳转到下一个界面
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN){
val intent = Intent(this,HomeActivity::class.java)
startActivity(intent)
}
return true
}

(2)隐示意图

跳转到同一部手机上的其他应用的某个界面
同⼀部⼿机上 其他APP A -> B app ⽀付功能(exported为true)
(action category) //意图过滤器

如果同一部手机中的app配置文件中的action name重复了,在跳转时会有弹窗提示你到底想要跳转到哪个app。

1
2
3
4
5
6
7
8
9
10
11
//当前app写入另一个app配置文件中的action name
val intent = Intent("com.example.dongge.pay")
//界面传值
intent.putExtra(name:"testKey",viewModel.number)
startActivity(intent)


//另一个界面获取值
val value = intent.getlntExtra(name: "testKey", defaultValue: 0)
binding.textView.text = "$value"

常用意图

Intent.ACTION_DIAL
打开拨号界面并显示指定的电话号码,但不会直接拨打电话。用户可以在拨号界面中确认号码并手动拨打电话(手动拨号)

1
2
3
val phoneNumber = "1234567890"
val intent = Intent(Intent.ACTION_DIAL,Uri.parse("tel:$phoneNumber"))
startActivity(intent)

Intent.ACTION_CALL 这个动作是直接拨打指定的电话号码,不需要用户确认。(直接呼叫)
需要注意的是,使用ACTION_CALL需要在AndroidManifest.xml中添加CALL_PHONE权限。

1
2
<!--这样做会在应用安装时向用户显示权限请求,用户需要授予应用拨打电话的权限才能使用ACTION_CALL。-->
<uses-permission android:name="android.permission.CALL_PHONE" />

实际上,从Android 6.0(API级别23)开始,仅在AndroidManifest.xml文件中添加CALL_PHONE权限是不够的。应用程序还需要在运行时请求CALL_PHONE权限,并且用户必须在应用程序中明确授予此权限。

1
2
3
4
5
6
7
8
9
//TakePicture请求图片
val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
if (it){
//用户同意
}else{
//用户不同意
}
}
permissionLauncher.launch(Manifest.permission.CALL_PHONE)
1
2
3
4
5
6
val phoneNumber = "1234567890"
val callIntent = Intent(Intent.ACTION_CALL).apply {
data = Uri.parse("tel:$phoneNumber")
}
startActivity(callIntent)

(三)权限申请

(相机 相片 联系人列表 打电话 使用网络)
权限是一种安全机制,用于限制应用程序对系统资源和用户数据的访问。
在应用程序需要访问受保护的资源或执行敏感操作时,必须请求相应的权限。
在Android中,权限通常在清单文件(AndroidManifest.xml)中声明,并且需要在运行时动态请求。

在AndroidManifest.xml文件声明自己需要什么权限

1
2
3
4
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.CALL_PHONE"/>

先检测是否有对应权限(用户是否已经同意过了),没有权限再去申请权限
checkSelfPermission
registerForActivityResult

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
//申请具体权限
//registerForActivityResult() 申请的结果
//ActivityResultContracts.RequestPermission() 申请什么权限:权限/访问视频/访问图片
val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
//处理的结果,用户同意或者不同意需要做什么
if (it){
//用户同意
}else{
// 用户拒绝了拨打电话权限,处理拒绝权限的逻辑
Toast.makeText(this, "拨打电话权限被拒绝", Toast.LENGTH_SHORT).show()
}
}
//具体申请什么权限,触发系统权限请求对话框,提示用户允许或拒绝电话权限
permissionLauncher.launch(Manifest.permission.CALL_PHONE)
}

跳转动画

创建资源文件夹
res -> New -> Android Resource Directory

anim -> New -> Android Resource File
Root element:scale缩放 alpha渐变 translate平移 rotate旋转

enter exit popEnter popExit

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%"
android:toXDelta="0%"
android:duration = "500" />

给activity添加切换动画
overridePendingTransition(R.anim.enter from rightR.anim.exit to left)

Activity 生命周期

为了在 activity 生命周期的各个阶段之间导航过渡,Activity 类提供了六个核心回调:onCreate()、onStart()、onResume()、onPause()、onStop() 和 onDestroy()。当 activity 进入新状态时,系统会调用其中每个回调。

生命周期.png
(界面的生命周期从创建一销毁经历的过程)
onCreate()
onStart()
onResume()
onPause()
onStop()
onRestart()
onDestroy()

  1. onCreate()
    当activity第一次创建时调用,用于初始化activity的基本组件,例如布局、视图和数据。
    创建界面
    还在创建,正在配置
    配置界面长什么样子

  2. onStart()
    当 activity 变得可见但还没有获得焦点时调用,用于准备开始用户交互。(Activity 变为可见时调用)

渲染界面
启动
渲染 = 绘制

  1. onResume()
    当 activity 获得焦点并开始与用户交互时调用,用于启动动画、音乐播放等用户体验相关的任务。( Activity 获得焦点并开始与用户交互时调用)
    渲染完毕,等待用户交互(界面看得见,可以进行交互了)
    展现在面前,等待交互,用户拖拉点拽
    ↓activity开始运行了

  2. onPause()
    当activity失去焦点但仍然可见时调用,用于暂停动画、音乐播放等用户体验相关的任务。(Activity失去焦点但仍可见时调用,通常用于保存数据或释放资源)
    在当前Activity被其他Activity覆盖或锁屏时调用;
    停止一切交互事件

  3. onStop()
    界面不可见(Activity完全不可见时调用)
    当activity不再可见时调用,用于释放资源、保存数据等清理工作。

  4. onRestart()
    在Activity从停止状态再次启动时调用(Activity由停止状态变为运行状态之前调用)

  5. onDestroy()
    当activity被销毁时调用,用于释放所有资源、取消注册的监听器等最终的清理工作(Activity销毁时调用,释放资源)。


进入后台:onPause() -> onStop()
从后台返回界面:onRestart() -> onStart() -> onResume()


从A界面切换到B界面
A -> B
A onPause()

B onCreate()
B onStart()
B onResume()

A onStop()

再从B界面返回到A界面
B onPause()

A onRestart()
A onStart()
A onResume()

B onStop()
B onDestory() (由于栈的原因,B返回到A界面就要被销毁了)


  1. onSaveInstanceState(outState: Bundle):Activity即将被销毁前调用,用于保存临时数据,以便在Activity重新创建时恢复状态。

  2. onBackPressed():用户按下返回键时调用,通常用于处理返回键的逻辑。


launchMode启动模式

android:launchMode=””限制activity在栈里面出现的方式
launchMode启动模式.png
如上表所示,”standard” 是默认模式,适用于大多数类型的 activity。对众多类型的 activity 而言,”singleTop” 也是常见且有用的启动模式。其他模式(”singleTask”、”singleInstance” 和 “singleInstancePerTask”)不适用于大多数应用。它们所形成的交互模式可能让用户感到陌生,并且与大多数其他应用差别较大。

android:launchMode=””
standard 默认的启动模式(标准) ——> A->B->C->D->A->B 始终创建新的activity实例
singleTop(栈顶复用) ——> 如果在栈的顶部有一个需要启用的对象,就直接用即可,不会再创建一个新的对象
     A->B->C->D->C(这里的C就无法复用,只能复用栈顶的)
     A->B->C(此时C在栈顶,若还想再启动一个C,此时就无需再创建新的,直接复用)
singleTask(栈内复用)
     A->B->C(栈内已有)
     如果想启用D(被singleTask修饰)则会另起一个任务栈
     D->
singleInstance(单例) ——> 栈里面如果存在某个界面,就直接从栈里面弹出来 复用,不会创建新的实例,把栈中已有的弹出来,该activity
始终是其任务中的唯一,同一个界面在栈里面只有一个对象。
singleInstancePerTask

手机屏幕的横竖屏

在清单文件(manifests -> AndroidManifest.xml)中

1
2
3
<activity android:name=".MainActivity"
android:screenOrientation="sensor">
</activity>

android:screenOrientation=”landscape” //横屏
android:screenOrientation=”portrait” //竖屏
android:screenOrientation=”sensor” //横竖交替
android:screenOrientation=”sensorLandscape” //会在横屏状态下开始,并自动旋转到竖屏模式
android:screenOrientation=”sensorPortrait” //会在竖屏状态下开始,并自动旋转到横屏模式
android:screenOrientation=”reversePortrait” //倒立
android:screenOrientation=”fullSensor“ //全自动切换(可以在四个方向上进行旋转)(一般用这个)

onSaveInstanceState()

(单界面、少变量时可以这么操作,但是最好使用 ViewModel)

旋转时(Activity状态发生变化时)界面会丢失数据

Activity先销毁再重建

界面销毁之前会调用
onSaveInstanceState 来存储丢失的数据
使用putInt()存储数据,在下一次创建时,在OnCreate中先判断Bundle中是否有存储的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)

val count = 5
outState.putInt("countKey", count)

val user = User("John", 30) // 自定义的Parcelable对象User
outState.putParcelable("userKey", user)
}



override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (savedInstanceState != null) {
val count = savedInstanceState.getInt("countKey")
val user = savedInstanceState.getParcelable<User>("userKey")

// 根据保存的数据进行相应的操作
}
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信