您的位置:首页 > 其它

Activity入门(一)

2016-04-05 20:42 211 查看

生命周期

onCreate():activity进行创建,在该方法中应调用setContentView(),findViewById()以及获取要展示的数据的方法(如调用managerQuery()去查询数据库中将要展示的数据)。
在该方法中可直接调用finish(),此时activity会立即执行onDestory(),中间的生命周期将不会被执行到。
onStart():在onCreate()或onRestart()之后执行。此时activity处于前台(可以拦截所有用户的操作),对用户不可见(类似于透明),且不能响应用户的操作。例如,在onResume()中Thread.sleep(5000)后再调用super.onResume(),那么从桌面上启动app时,显示的依旧是桌面,但对桌面上的任何操作都无法得到响应。因此,可以认为activity对用户不可见(简单理解为透明的),且不能响应用户操作。
onResume():onStart()之后执行。此时activity对用户已经可见,并且可以响应用户操作
onPause():activity已进入后台,但依旧可见。该方法中适合停止动画等非常消耗cpu的操作,保存全局数据以及关闭独占资源(如相机等)。由于A启动B时,首先执行的是A中的onPause()方法,因此为了提高显示B界面的速度,onPause()中严禁执行耗时操作。
onStop():当前activity对用户不可见时,执行该方法。
onDestroy()为当前activity进行最后的清理工作,如关闭与当前activity关联的线程等。不能在该方法中保存数据。用户调用finish()或者系统为节约内存而暂时清理掉activity实例时,会导致该方法被回调(可通过调用isFinishing()区分这两种情况)。

onSaveInstanceState()与onRestoreInstanceState()

onSaveInstanceState():在onStop()之前调用,但与onPause()的顺序不固定。该activity可能会再次出现前台时才使用该方法保证数据。如切换到桌面,启动另一个activity,那么这个activity就有可能会再次出现在前台,所以为了安全,需要使用该方法保存数据。但返回时不会调用,例如从activity
B中返回activity A时,activity B中的该方法不会被调用。
onSaveInstanceState()中的参数会在activity重建时传递到onCreate()和onRestoreInstanceState()中。
onRestoreInstanceState():用于恢复onSaveInstanceState()保存的状态,在onStart()之后执行。但是一般的恢复状态在onCreate()中进行,该方法只是用于子activity进行个性化恢复。并且onCreate中需要判断参数是否为null,但onRestoreInstanceState()中不需要进行判断。
在默认情况下,这两个方法会自动保存并恢复View的状态(每一个View中都有onSaveInstanceState()与onRestoreInstanceState()),如Edittext中用户输入的文字,ListView滚动的位置等。

onPause()与onSaveInstanceState()

由于在内存紧张时,系统会关闭处于pause状态的activity,因此应该在onPause()中保存一些全局数据(如内容提供者,文件等)。
onSaveInstanceState()却是适合用于保存activity自身的数据。
在正常的生命周期中,onSaveInstanceState()是不会被调用的,但onPause会。

A启动B

生命周期执行顺序为:A#onPause()->B#onCreate()->#B#onStart()->B#onResume()->A#onStop()。

onConfigurationChanged

屏幕方向等手机配置发生变化时,会导致当前的activity被销毁重建,在该过程中会调用onSaveInstanceState()与onRestoreInstanceState()方法。
如果想不重建activity,需要在<activity>中配置configChanges属性,比如configChanges="orientation",那么当屏幕旋转时就不会引起activity重建。但会调用onConfigurationChanged()。即:配置在configChanges中的手机配置发生变化时,不会引起activity的销毁重建,只会调用Activity#onConfigurationChanged()的调用。
常用配置如下:
locale|keyboardHidden|orientation|screenSize:分别表示手机位置发生变化(一般则修改系统语言),键盘可访问性发生变化以及屏幕方向。
注:配置configChanges时,一定要加上screenSize,不然不会调用onConfigurationChanged()。这是因为在横竖屏切换的时候,screenSize也发生了变化,如果不配置该属性,照样会销毁activity然后重建。

操作

设置动画

为activity设置动画,除了在代码中用overridePendingTransition()方法外,还可以在清单文件中配置theme来实现。示例

<style name="mystyle">
<item name="android:windowAnimationStyle">@style/animation</item><!-- 配置动画 -->
<item name="android:windowNoTitle">true</item>
</style>

<style name="animation" mce_bogus="1" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/anim_enter</item>
<item name="android:activityOpenExitAnimation">@anim/anim_exit</item>
<item name="android:activityCloseEnterAnimation">@anim/back_enter</item>
<item name="android:activityCloseExitAnimation">@anim/back_exit</item>
</style>
清单文件中的配置为
android:theme="@style/mystyle"
如果写在<application>结点下,就会作用于所有的activity;如果写在单一的activity下,就只会作用于当前的activity。
其中的几个item的说明:

android:activityOpenEnterAnimation:当打开activity时,被打开的activity进入时的动画。

android:activityOpenExitAnimation:当打开activity时,旧的activity退出时的动画。

android:activityCloseEnterAnimation:当关闭activity时,新的(要显示出来的)activity进入时的动画。

android:activityCloseExitAnimation:当关闭activity时,旧的(要退出的)activity退出时的动画。

从底部弹起

弹出的菜单项可以通过activity来完成。效果:



其中拍照等就是一个activity界面。该activity的theme如下:

<style name="TransparentBottom" parent="android:Theme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@style/AnimBottom</item>
<item name="android:backgroundDimEnabled">true</item>
<!-- 模糊 -->
</style>

其中AnimBottom为:

<style name="AnimBottom" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>

常用方法

attach():Activity在onCreate之前调用attach方法,在attach方法中会创建Window对象。window对象创建时并没有创建DecorView对象。用户在Activity中调用setContentView,该方法会调用Window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的View
添加到DecorView中。这就是Activity显示界面的过程。

<activity>

windowSoftInputMode

设置软键盘模式。主要解析adjustResize与adjustPan。前者重绘整个屏幕,会调用到View中的onSizeChanged()方法;后者不会重绘整个屏幕,它只是把屏幕中的组件进行平移,把获取焦点的组件显示出来即可,未获取焦点的则还会被软键盘遮盖。但是是adjustResize则不会。

adjustResize的图:



adjustPan的图:



从两个图可以看见:第一个图中(adjustResize)当软键盘弹起的时候,ListView会自动滚动到最后一个条目,因为它重绘了整个屏幕,相当于ListView重新加载一次。而第二个界面中(adjustPan),当软键盘弹起时,只是把当前屏幕中最后一个条目给顶起来,并不显示ListView中的最后一个条目。

taskAffinity

它指明当前的activity所希望属于的栈。如果没有指定,就按<application>中的taskAffinity的值,如果后者也没有指定,就指的是在清单文件中声明的包名。一个栈有一个affinity,它的值指的是这个栈的根activity的taskAffinity的值。因此,当所有的activity都不指定taskAffinity的时候,这些activity都会进入同一个栈中(因为taskAffinity的值都是清单文件中声明的包名)。

allowTaskReparenting

是否允许当前的activity重新宿主到具有相同的affinity的栈中,当该栈处于前台时。假设应用A有一个activityA的taskAffinity的值为com.example.demo1,且allowTaskReparenting为true;应用B有一个activityB的taskAffinity也为com.example.demo1。那么先运行应用A,运行后按小房子。再运行应用B,这时会发现显示的是activityA的内容。这是因为,activityA允许该activity重新宿主。因此,当activityB启动的时候,会建立一个affinity为com.example.demo1的栈,这个栈的affinity和activityA的taskAffinity一样,所以activityA就重新宿主(也就是移动到了activityB启动的栈中)了。再比如,应用A中启动了应用B的activityA(该activity的此属性值为true),那么当运行应用B时,显示的会是activityA(从应用A的task中重宿到应用B的task中)。

excludeFromRecents

是否从最近浏览中删除。如果为true,则在最近浏览中无该应用图标,否则有。默认值为false。

exports

是否允许别的应用程序打开该activity,true是允许。false是不允许。它的默认值是根据<intent-filter>来的,如果含有<intent-filter>,则默认值为true。否则默认值为false。

stateNotNeeded

在正常情况下,在一个activity调用finish()之前会调用onSavaInstanceState()用来保存该activity的状态,并会将它的状态存储到一个Bundle的对象中。当该activity再次启动时,就会把该Bundle对象传到onCreate()方法中。如果该属性设置为true了,那么就不会调用onSavaInstanceState()方法,那么onCreate()方法中传入的参数就是null,就像该activity第一次被创建时一样。默认值是false。

alwayRetainTaskState

当某个栈处于后台的时间过长,系统会自动回收这个栈中的除了根activity外的所有activity。如果在根activity设置了该属性并且值为true,那么这个栈中的所有activity都不会被系统回收,无论离开多长时间。

clearTaskOnLaunch

根activity该值为true,那么该栈中除了根activtiy外的所有activity,在该栈一进入后台的时候都会被清空。如果allowTaskReparenting与clearTaskOnLaunch都设置为true,那么在启动某一个栈的时候,该栈中能重新宿主的activity都会重新宿主,不能重新宿主的activity都会被清掉。该属性只对根activity设置有效,task中其它activity设置无效。

finishOnTaskLaunch

它和clearTaskOnLaunch类似,但是只能作用于一单个的activity,而不能作用于一个栈。当某一个activity的该属性值设置为true时,该activity所处的栈再次处于前台时,这个activity会finish掉,即使它设置了allowReparenting=true。

启动模式

定义activity的启动模式有两种方式:清单文件和通过intent.setFlag()。如果两者同时存在,以后者为准

standard

标准启动模式。谁启动了该activity,那么该activity就会运行在启动它的activity所在的栈中。因此,在非activity中启动activity时,必须为intent设置FLAG_ACTIVITY_NEW_TASK标识,因为非activity没有任务栈。

singleTask

参考

1. 设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的task是否存在;如果存在,它就会在这个任务中启动,否则就会在新任务栈中启动。因此,如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。这也可以解释为什么在同一个应用中启动singleTask的activity会是在同一个task,而不同应用中启动时却不是同一个task。因为默认时目标activity的taskAffinity为应用的包名,不同应用时taskAffinity与启动activity所在的task的affinity值不一致,因此目标activity会在新的task中启动。
2. 如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。如果不存在,就新建一个目标activity的实例,并压入相应的task的顶端。
3,如果目标activity不是在新task中启动,那么目标activity所在的task会被挪移到前台,从而该task中的activity位于启动activity前面。如下:



文字说明为:A representation of how an activity with launch mode "singleTask" is added to the back stack. If the activity is already a part of a background
task with its own back stack, then the entire back stack also comes

forward, on top of the current task.

singleInstance

新建一个栈,并将该activity放到该栈中,而且这个栈中不会放入别的任意的activity。

当启动模式为上述两种时,startActivityForResult()是无效的。onActivityResult()会立即执行,并且resultCode为RESULT_CANCELED。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: