android四大组件之activity

一、activity的作用

向用户呈现不同的操作界面。

二、activity的使用

1、配置activity

配置Activity如下:

<activity 
    android:name=".MainActivity" 
    android:icon="@mipmap/ic_launche" 
    android:label="label" 
    android:exported="true" 
    android:launchMode="standard">
</activity>

android:name:指定该Activity的实现类的类名

android:icon:指定该Actvity对应的图标(ActionBar)

android:label:指定该Actvity对应的标签(ActionBar)

android:exported:指定该Actvity是否允许被其他应用调用

android:launchMode:指定该Actvity的加载模式

2、启动activity

1)、startActivity(Intent intent):启动其他Activity。在被启动Activity中执行finish()或者按返回键,不会回调原Activity的onActivityResult

2)、startActivityForResult(Intent intent, int requestCode)

a、以指定的请求码(requestCode)启动其他Activity,重写onActivityResult(int requestCode, int resultCode, Intent data)获取新启动的Activity返回的结果。在被启动Activity中执行finish()或者按返回键都会回调onActivityResult

b、setResult()可以返回被启动activity的结果代码和数据,只执行setResult()activity不会结束,还要执行finish()或者按返回。在startActivity()启动的activity中执行setResult()没有意义。

3、关闭activity

1)、finish():结束当前Activity

2)、finishActivity(int requestCode):结束以startActivityForResult()方法启动的另一个Activity,requestCode就是startActivityForResult()中传入的requestCode。

三、Bundle交换数据

使用方法

1、设置Bundle

intent.putExtras(bundle);

2、设置key-value

intent.putExtra(key, value);

3、上面两种方式最终数据都放在Intent内部的Bundle中。

四、activity的生命周期

官方生命周期图:

1、正常情况下的生命周期

1)、启动activity:系统先调用onCreate(),然后调用onStart(),最后调用onResume()方法,activity进入运行状态。

2)、activity跳到其他activity或者锁屏或者回到主屏:系统会调用onPause()方法,然后调用onStop(),暂停当前activity的执行.

3)、回到原来的activity或者解锁屏:系统会调用onRestart(),onStart(),onResume()方法,再次进入运行状态

4)、当前Activity处于被覆盖状态或者后台不可见状态,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。

5)、用户退出当前Activity(按返回键):系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。用户回到lauch界面,一次调用onPause方法,然后调用onStop方法,不会调用onDestory方法。

6)、onStart():activity可见了,但是还没有出现在前台,还无法和用户交互。

onResume():还没有绘制view,加入延时时界面是空白

7)、onPause():表示activity正在停止,此时可以做一些存储数据,停止动画等工作,注意不能太耗时,因为这会影响到新activity的显示,onPause必须先执行完,新的activity的onCreate,onStart,onResume才会执行,然后再执行该activity的onStop、onDestroy。因此在onPause()中不能做耗时的回收,在onStop()中做重量级(耗时)的回收。

8)、当activity中弹出dialog对话框的时候,activity不会回调onPause(因为dialog是activity中的一个组件,activity没有变化,所以不会影响activity的生命周期)。当activity启动dialog风格的activity的时候,此activity会回调onPause函数,不会回调onStop

9)、只执行onPause,不执行onStop的情况

a、当activity启动dialog风格的activity

b、当activity启动主题是android:theme="@android:style/Theme.Translucent" 的activity,即主题是透明的activity

10)、a启动b时(a中没有执行finish()),周期函数如下:a.onPause->b.onCreate->b.onStart->b.onResume->a.onStop

2、异常情况下的生命周期

1)、资源相关的系统配置发生改变导致activity被杀死并重新创建

比如说当前activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,activity就会被销毁并且重新创建。

系统配置发生改变以后,activity会销毁,onPause,onStop,onDestory均会被调用,由于activity是在异常情况下终止的,系统会调用onSaveInstance来保存当前activity状态,这个方法的调用时机是在onStop之前。与onPause没有既定的时序关系,当activity重新创建后,系统会调用onRestoreInstanceState,并且把activity销毁时onSaveInstanceState方法保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。onRestoreInstanceState()在onStart()方法后回调。

在onSaveInstanceState和onRestoreInstanceState方法中,系统自动为我们做了一些恢复工作,如:文本框(EditeText)中用户输入的数据,ListView滚动的位置等,这些view相关的状态系统都能够默认为我们恢复。可以查看view源码,和activity一样,每个view都有onSaveInstanceState方法和onRestoreInstanceState方法。其他的一些业务数据需要我们放在Bundle中。

2)、资源内存不足导致低优先级的activity被杀死
这里的情况和前面的情况1)数据存储和恢复是完全一致的,activity按照优先级从高到低可以分为如下三种:
a、前台activity---正在和用户交互的activity,优先级最高
b、可见但非前台activity---比如activity中弹出了一个对话框,导致activity可见但是位于后台无法和用户直接交互。
c、后台activity---已经被暂停的activity,比如执行了onStop,优先级最低。

3)、防止重新创建activity:activity指定configChange属性来不让系统重新创建activity。android : configChanges = "orientation|screenSize"。orientation表示设备旋转,横向显示和竖向显示模式切换,screenSize表示屏幕大小变化。因为横竖屏切换时屏幕大小也会变化,所以必须同时设置才有效果。指定configChange属性后不会执行activity的生命周期方法、onSaveInstanceState和onRestoreInstanceState,只会回调onConfigurationChanged。

五、启动模式

1、启动模式作用

1)、Activity栈

Android 使用Task管理多个Activity。当我们启动一个应用时Android会为之创建一个Task,然后启动AndroidManifest中定义的入口Activity。Activity.getTaskId()方法可以获取Activity所在Task的ID。我们可以把Task理解为Activity栈,先启动的Activity放在栈底,后启动的Activity放在栈顶。

当点击导航栏的任务栏键就会出现当前所有Activity栈,注意应用退出后任务栏也会保留该应用Activity栈的残影,即使应用已经死了,目的是用户可以方便的切回去,只是这种时候的切回去是应用的重启动,因为以前的Task已经不在了。

2)、启动模式的作用

负责管理实例化、启动Activity的方式,控制Activity和Task之间的加载关系

2、启动模式分类

1)、特点

a、standard:标准模式。系统默认使用该模式启动Activity,每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在。这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中。

b、singleTop:栈顶单例模式。如果在栈顶已经有该Activity实例,Intent不会再创建新的Activity,该Activity的onNewIntent(intent)被回调,intent就是startActivity时传入的intent。onCreate、onStart、onResume不会回调,因为该Activity实际没有改变。

c、singleTask:栈内单例模式。singleTask模式的Activity只允许在Task中有一个实例。如果Task中已经有了一个实例,该Activity将移动到栈顶并且清除该Activity上面的Activity,同时intent将被通过onNewIntent()发送。如果不存在,就创建。设置TaskAffinity(且和当前包名不一样)就会单独用一个名为TaskAffinity的任务栈启动该Activity。

d、singleInstance:全局单例模式。全局只有一个实例,位于新的Task中(如没有设置taskAffinity,任务栈的名字为默认名字,和包名一样),并且Task中只有该activity。如果该Activity实例已经存在,启动时回调onNewIntent()。Task只有一个Activity实例,在该模式的activity中启动其他activity,其他activity也不会放在该模式activity的任务栈中。

2)、应用场景

a、singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。(activity通过onNewIntent()获取新传入的数据)

b、singleTask适合作为程序入口点。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。

c、singleInstance适合如果想实现其他程序和我们的程序共享这个Activity的实
例(即两个程序启动的都是同一个Activity实例),应该如何实现呢?使用前面3种启动模式肯定是做不到的,因为每个应用程序都会有自己的
返回栈,同一个Activity在不同的返回栈中入栈时必然创建了新的实例。而使用
singleInstance模式就可以解决这个问题,在这种模式下,会有一个单独的返回栈来管理这个
Activity,不管是哪个应用程序来访问这个Activity,都共用同一个返回栈,也就解决了共享
Activity实例的问题。

3)、TaskAffinity

默认情况下,所有activity所需的任务栈的名字为应用的包名,可以通过给activity指定TaskAffinity属性来指定任务栈,如果TaskAffinity指定的任务栈不存在就新建一个任务栈。这个属性值不能和包名相同,否则就没有意义。点击最近ativity时不同任务栈分别显示(微信的小程序就和微信放在不同任务栈中)。

下图是微信打开3个小程序的任务栈情况,其中com.tencent.mm是微信的任务栈,.AppBrandUI3、.AppBrandUI2、.AppBrandUI是3个小程序的任务栈。

注意TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,其他情况没有意义。如果从singleInstance的activity启动standard,如果设置了TaskAffinity,standard就放在TaskAffinity指定任务栈中。

注意不同应用如果两个activity的taskAffinity一样,它们会放在同一任务栈中。

注意:命令"adb shell dumpsys activity activities"可以查看各个任务栈中的activity,然后搜索"Running activities"就是任务栈中的activity。

如果start一种启动模式的Activity,然后又返回了。这时通过上面的命令是看不到这个activity的,因为返回的时候activity已经销毁了。

4)、allowTaskReparenting

一般情况下:应用A启动应用B的activity,应用B的activity没有放在应用B的任务栈中,而是应用A的任务栈中。但是allowTaskReparenting可以改变这种策略。

allowTaskReparentin的主要作用是activity的迁移,即从一个task迁移到另一个task,这个迁移跟activity的taskAffinity有关。当allowTaskReparenting的值为“true”时,表示Activity能从启动的Task(另一个应用启动,所以当前的Task affinity不是这个Activity应该的Task)移动到和该Actvity taskAffinity对应的的Task(当这个Task进入到前台时),当allowTaskReparenting的值为“false”,表示它必须呆在启动时呆在的那个Task里。比如现在有两个应用A和B,A启动了B的一个ActivityC,然后按Home键回到桌面,再单击B应用时,如果此时,allowTaskReparenting的值为“true”,那么这个时候并不会启动B的主Activity,而是直接显示已被应用A启动的ActivityC,我们也可以认为ActivityC从A的任务栈转移到了B的任务栈中。

注意allowTaskReparenting仅限于singleTop和standard模式。因为启动另一个应用singleTask和singleInstance模式的Activity时,这个Activity会放在另一个Task中。

3、一个应用启动另一个应用的activity时不同启动模式任务栈的变化

1)、启动standard

新的actiivty和原应用在一个任务栈

2)、启动singleTop

新的actiivty和原应用在一个任务栈

3)、启动singleTask

activity设置TaskAffinity或者不设置TaskAffinity,新的actiivty在自己的任务栈中,不和原应用在一个任务栈

没有设置TaskAffinity

设置TaskAffinity为com.other.taskAffinity

4)、启动singleInstance

新的actiivty不和原应用在一个任务栈

六、Intent中的flag

FLAG_ACTIVITY_SINGLE_TOP :和 Launch Mode 中的 singleTop 效果是一样的。
FLAG_ACTIVITY NEW TASK :和 Launch Mode 中的 singleTask 效果是一样的。
FLAG ACTIVITY CLEAR TOP :在 Launch Mode 中没有与此对应的模式,如果要
启动的 Activity 已经存在于枝中,则将所有位于它上面的 Activity 出柱。 singleTask
默认具有此标记位的效果。

注意:FLAG_ACTIVITY_NEW_TASK默认情况不会使用新的任务栈启动Activity。目标Actiivty配置TaskAffinity并且和应用包名不一样才会使用新的任务栈启动Actiivty。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值