怎么在刚android启动activityy时候加一个过渡图片

10279人阅读
一、为什么要了解Activity的生命周期
了解Activity的生命周期的根本目的就是为了设计用户体验更加良好的应用。因为Activity就相当于MVC中的View层,是为了更好的向用户展现数据,并与之交互。了解Activity的生命周期和各回调方法的触发时机,我们可以更好的在合适的地方向用户展现数据(因为每个应用每个Activity的作用不同,所以具体每个回调方法的最佳实践不好把握,但是只要遵循最基本的原则即可),保证数据的完整性和程序的良好运行。
下面是官方文档的原话:
Managing the lifecycle of your activities by implementing callback methods is crucial to developing a strong and flexible application. The lifecycle of an
activity is directly affected by its association withother activities, its task and back stack.
翻:对于开发一个强大和灵活的应用程序,实现Activity的回调方法来管理Activity的生命周期至关重要。
一个Activity的生命周期直接影响与它结合的其他Activitys和它的任务返回堆栈。
二、Activity生命周期的表现
除了我们自行启动(start)或者结束(finish)一个Activity,我们并不能直接控制一个Activity 的生命状态,我们只能通过实现Activity生命状态的表现——即回调方法来达到管理Activity生命周期的变化。
具体如下图所示:
通过上图,我们可以看到这些方法定义了Activity整个生命周期。
为什么要定义这么多生命周期的方法呢?最主要的目的就是把Activity的各个不同的状态区分处理。
通过实施这些方法,您可以监视Activity生命周期中的三个嵌套循环:
1、entire&lifetime&(整个生命周期)
一个Activity整个生命周期,存在于onCreate()方法和onDestroy()调用之间。你的Activity应该在onCreate()方法里执行设置“全局”状态(如定义布局)。并在onDestroy()方法里释放所有剩余资源。例如,如果你的活动有一个线程在后台运行下载网络数据,它可以在onCreate()中创建该线程,然后在onDestroy()中停止线程。
2、visible&lifetime(可见生命周期)
一个Activity可见生命周期,存在于onStart()和onStop()调用之间。在此期间,用户可以看到屏幕上的activity并与之交互。当一个其他的Activity启动,并且这个Activity完全不可见的时候,onStop()方法就会被调用。在这两个方法,你可以保持该Activity需要展示给用户的资源。例如,您可以在onStart()方法里注册一个BroadcastReceiver来监控你的UI的变化,并在onStop()方法里注销它。在整个生命周期的活动中,系统可能会调用onStart()和onStop()多次,因为活动之间交替进行隐藏或显示给用户。
3、&foreground&lifetime(前台生命周期)
一个Activity前台生命周期,存在于onResume()和onPause()调用之间。在这段时间里,这个Activity在其他所有Activity的前面,拥有用户输入焦点。一个Activity可以经常在前台状态发生转换—比如,当设备休眠或者弹出了个对话框。因为经常会发生转换,所以在这两个方法之间的代码应该是轻量级的,防止导致其他转换变慢使得用户需要等待。
一个Activity本质上只有三种状态:
Resumed(运行)、Paused(暂停)、Stopped(停止),因为从Activity被创建之后,它只可能在这三种状态保持长久的停留,其他的回调方法结束后的状态都只能称之为过渡状态。比如进入到onStart方法后,执行完该方法,会立即进入到OnResume方法。(这里所说的状态都是指对应的某个方法返回之后)
即使一个Activity进入到Paused或者Stopped方法,它仍然是存在的,被保存在任务返回堆栈中。它仍然保持着自身的所有实例和状态,所以根本不用担心它在返回到onResume方法时,实例会变为null,或者控件的事件监听不了(我以前就担心过这个问题)。唯一需要考虑的就是,系统在内存不足的情况下,杀死在Paused或者Stopped状态下的Activity。
当一个Activity在Resumed状态下,它是不会因内存不够而被系统直接杀死(在极端的情况下也有可能被杀死,但是一般不会考虑这种情况)。只有进入Paused或者Stopped状态才会,而且可能根本就不会去调用onStop()和onDestory()方法,所以onPause()方法是我们最大程度上保证Activity在销毁之前能够执行到的方法。因此,如果你的某个Activity需要保存某些数据到数据库,您应该在onPause()里编写持久化数据的代码。但要注意,你应该选择哪些信息必须保留在onPause(),因为这个方法任何阻塞程序都会阻止过渡到下一个Activity,这样给用户体验就感觉十分缓慢。
更多关于Activity被杀死的问题,可以参考
三、生命周期的验证
1、单个Activity生命周期的变化
写一个简单的Activity,重写所有生命周期的方法,如下:
public class LifecycleActivity extends Activity {
private Button mBtn1;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println(&LifecycleActivity onCreate&);
setContentView(R.layout.life_cycle_activity);
mBtn1 = (Button) findViewById(R.id.btn1);
mBtn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
protected void onStart() {
super.onStart();
System.out.println(&LifecycleActivity onStart&);
protected void onResume() {
super.onResume();
System.out.println(&LifecycleActivity onResume&);
protected void onPause() {
super.onPause();
System.out.println(&LifecycleActivity onPause&);
protected void onStop() {
super.onStop();
System.out.println(&LifecycleActivity onStop&);
protected void onDestroy() {
super.onDestroy();
System.out.println(&LifecycleActivity onDestroy&);
protected void onRestart() {
super.onRestart();
System.out.println(&LifecycleActivity onRestart&);
}当进入这个Activity时,打印如下:
当点击按钮,调用finish()方法后,打印如下:
如果我们将finish()调用直接放在onCreate方法里,那么打印如下:
如果我们将finish()调用直接放在onStart方法里,那么打印如下:
如果我们将finish()调用直接放在onResume方法里,那么打印如下:
如上图的结果,所以很多人喜欢把Activity的生命周期表示为一种对称的结构:
2、Activity之间切换时生命周期的变化
1、基本的变化
现在有两个Activity,LifecycleActivity和LifecycleOtherActivity,都重写了所有的生命周期方法,并加上了打印输出。
进入第一个Activity——LifecycleActivity,打印如下:
06-07 23:16:31.389: I/System.out(1341): LifecycleActivity onCreate
06-07 23:16:31.455: I/System.out(1341): LifecycleActivity onStart
06-07 23:16:31.455: I/System.out(1341): LifecycleActivity onResume
一个Activity的创建,没什么可说的。
在LifecycleActivity中有一个按钮,点击事件为
public void onClick(View v) {
startActivity(new Intent(LifecycleActivity.this, LifecycleOtherActivity.class));
}点击该按钮,打印如下:06-07 23:40:40.545: I/System.out(1409): LifecycleActivity onPause
06-07 23:40:40.585: I/System.out(1409): LifecycleOtherActivity onCreate
06-07 23:40:40.585: I/System.out(1409): LifecycleOtherActivity onStart
06-07 23:40:40.585: I/System.out(1409): LifecycleOtherActivity onResume
06-07 23:40:41.176: I/System.out(1409): LifecycleActivity onStop启动一个全屏显示的LifecycleOtherActivity,前面的LifecycleActivity肯定是要Stopped,但是这个调用的顺序一定要注意。它是先onPause,然后等LifecycleOtherActivity执行完onResume方法后,在执行的onStop方法。这也是为什么强调在onPause方法里面,我们只能去执行一些轻量级的代码。
现在LifecycleOtherActivity处于前台,并拥有用户焦点,现在点击返回按钮,打印如下:
06-07 23:47:21.796: I/System.out(1508): LifecycleOtherActivity onPause
06-07 23:47:21.815: I/System.out(1508): LifecycleActivity onRestart
06-07 23:47:21.815: I/System.out(1508): LifecycleActivity onStart
06-07 23:47:21.815: I/System.out(1508): LifecycleActivity onResume
06-07 23:47:22.295: I/System.out(1508): LifecycleOtherActivity onStop
06-07 23:47:22.295: I/System.out(1508): LifecycleOtherActivity onDestroy按下返回按钮,相当于finish掉了LifecycleOtherActivity,看它的执行过程,也是先暂停自身,然后再去重启LifecycleActivity,等LifecycleActivity重启完毕后,在调用onStop和onDestory方法。
2、启动对话框样式的Activity
现在有两个Activity,LifecycleActivity和LifecycleDialogActivity(对话框样式的Activity),都重写了所有的生命周期方法,并加上了打印输出。
进入第一个Activity——LifecycleActivity,打印如下:
06-07 23:16:31.389: I/System.out(1341): LifecycleActivity onCreate
06-07 23:16:31.455: I/System.out(1341): LifecycleActivity onStart
06-07 23:16:31.455: I/System.out(1341): LifecycleActivity onResume
一个Activity的创建,没什么可说的。
在LifecycleActivity中有一个按钮,点击事件为public void onClick(View v) {
startActivity(new Intent(LifecycleActivity.this, LifecycleDialogActivity.class));
}点击该按钮,打印如下:06-08 00:01:04.245: I/System.out(1508): LifecycleActivity onPause
06-08 00:01:04.325: I/System.out(1508): LifecycleDialogActivity onCreate
06-08 00:01:04.325: I/System.out(1508): LifecycleDialogActivity onStart
06-08 00:01:04.325: I/System.out(1508): LifecycleDialogActivity onResum启动一个对话框样式的LifecycleDialogActivity,并不会调用onStop方法
现在LifecycleDialogActivity处于前台,并拥有用户焦点,现在点击返回按钮,打印如下:
06-08 00:02:05.535: I/System.out(1508): LifecycleDialogActivity onPause
06-08 00:02:05.625: I/System.out(1508): LifecycleActivity onResume
06-08 00:02:06.165: I/System.out(1508): LifecycleDialogActivity onStop
06-08 00:02:06.165: I/System.out(1508): LifecycleDialogActivity onDestroy
可以看到在LifecycleDialogActivity暂停之后,之前调用的是LifecycleActivity的onResume方法。
3、启动一个普通的对话框?
在LifecycleActivity中有一个按钮,点击事件为
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(LifecycleActivity.this);
&&& builder.setTitle(&我是一个对话框&).setPositiveButton(&确定&, null);
builder.create().show();
}点击该按钮,可以发现,没有发现任何打印,也就是LifecycleActivity的生命周期没有任何改变。
4、LifecycleActivity中按钮的点击事件改成如下,并重写finish和startActivity,在里面也增加打印输出。
mBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(new Intent(LifecycleActivity.this, LifecycleOtherActivity.class));
System.out.println(&ABCDEFG&);
});点击改按钮,打印如下:
06-08 22:07:26.599: I/System.out(560): LifecycleActivity finish
06-08 22:07:26.619: I/System.out(560): LifecycleActivity startActivity
06-08 22:07:26.619: I/System.out(560): ABCDEFG
06-08 22:07:26.619: I/System.out(560): LifecycleActivity onPause
06-08 22:07:26.671: I/System.out(560): LifecycleOtherActivity onCreate
06-08 22:07:26.671: I/System.out(560): LifecycleOtherActivity onStart
06-08 22:07:26.671: I/System.out(560): LifecycleOtherActivity onResume
06-08 22:07:27.510: I/System.out(560): LifecycleActivity onStop
06-08 22:07:27.510: I/System.out(560): LifecycleActivity onDestroy
这里面涉及到Activity的管理问题,没有太多的研究,不太清楚,不过大概可以理解为finish和startActivity都是一个异步阻塞的过程,它必须要等到他们所在的那个方法执行完毕后,接着去finish或者start一个Activity,并且startActivity先于finish解除阻塞。
四、回调方法应该干些甚么
回调方法的作用,就是通知我们Activity生命周期的改变,然后我们可以处理这种改变,以便程序不会崩溃或者数据丢失等等,也就是拥有更好的用户体检,那么这么多回调方法里到底应该怎么做呢?
这个问题不好总结,因为不同的应用、不同的Activity所干的事都不一样,有时候我们甚至只需要实现一个onCreate就行了。所以下面所说的,看看即可,不一定符合所有的情况。
1、onCreate
最重要是在里面调用setContentView,还可以在里面初始化各控件、设置监听、并初始化一些全局的变量。
因为在Activity的一次生命周期中,onCreate方法只会执行一次。在Paused和Stopped状态下恢复或重启的下,这些控件、监听和全局变量也不会丢失。即便是内存不足,被回收了,再次Recreate的话,又是一次新的生命周期的开始,又会执行onCreate方法。
还可以在onCreate执行数据操作,比如从Cursor中检索数据等等,但是如果你每次进入这个Activity都可能需要更新数据,那么最好放在onStart里面。(这个需要根据实际情况来确定)
2、onDestory
确定某些资源是否没有被释放,做一些最终的清理工作,比如在这个Activity的onCreate中开启的某个线程,那么就要在onDestory中确定它是否结束了,如果没有,就结束它。
3、onStart和onRestart、onStop
Activity进入到Stopped状态之后,它极有可能被系统所回收,在某些极端情况下,系统可能是直接杀死应用程序的进程,而不是调用onDestory方法,所以我们需要在onStop方法中尽可能的释放那些用户暂时不需要使用的资源,防止内存泄露。
尽管onPause在onStop之前执行,但是onPause只适合做一些轻量级的操作,更多的耗时耗资源的操作还是要放在onStop里面,比如说对数据保存,需要用到的数据库操作。
因为从Stopped状态重启之后, onStart和onRestart方法都会被执行,所以我们要判断哪些操作分别要放在哪个方法里面 。因为可能在onStop方法里面释放了一些资源,那么我们必须要重启他们,这个时候这些重启的操作放在onStart方法里面就比较好(因为onCreate之后也需要开启这些资源)。那些因为Stopped之后引发的需要单独操作的代码,就可以放在onRestart里面。
4、onResume和onPause
onPause和onResume中做的操作,其实意义上和onStart和inStop差不多,只不过是要更轻量级的,因为onPause不能阻塞转变到下一个Activity。
比如:停止动画、取消broadcast&receivers。当然相应的需要在onResume中重启或初始化等等。
有时候也需要在onPause判断用户是调用finish结束这个Activity,还是暂时离开,以便区分处理。这时候可以调用isFinishing()方法来判断。如果是用户finish这个Activity,那么返回为true,如果只是暂时离开或者被系统回收的话,就返回false。
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:750355次
积分:8732
积分:8732
排名:第1024名
原创:113篇
转载:72篇
评论:247条
记录自己进步的点点滴滴,让懒惰的我能够一直的走下去。。。
(1)(1)(1)(2)(3)(3)(1)(1)(1)(1)(1)(8)(16)(4)(11)(26)(18)(23)(54)(3)(7)4249人阅读
&本文为原创文章,欢迎转载!转载时请注明出处:
& & 上篇文章分析完了task的创建或者复用,接下来接着分析activity在启动过程中还有哪些工作需要去完成?首先给出整个activity的过程图。
1. Starting Window
& & 当该activity运行在新的task中或者进程中时,需要在activity显示之前显示一个Starting Window。如上图所示的setAppStartingWindow()方法,这个Starting Window上并没有绘制任何的view,它就是一个空白的Window,但是WMS赋予了它一个animation。这个Starting Window的处理过程需要注意几点:
& & ·1. 在AMS请求WMS启动Starting Window时,这个过程是被置在WMS的消息队列中,也就是说这个过程是一个异步的过程,并且需要将其置在WMS消息队列的队首。
& & &一般情况下,Starting Window是在activity Window之前显示的,但是由于是异步过程,因此从理论上来说activity Window较早显示是有可能的,如果这样的话,Starting Window将会被清除而不再显示。例如在addStartingWindow()@PhoneWindowManager.java方法调用addView之前做一个sleep操作,结果就可能不显示Starting
setAppStartingWindow()@WindowManagerService.java
& & 2.&Starting Window是设置了Animation的
addStartingWindow()@PhoneWindowManager.java
& & 3.&Starting Window同普通的activity
Window一样,均为一个PhoneWindow,其中包看着DecorView和ViewRoot。
addStartingWindow()@PhoneWindowManager.java
2. 启动新进程
& & 如果新启动的activity需要运行在新的进程中,那么这个流程就涉及到了一个新进程的启动,由于画图的局限性,这个过程在上图中没有体现出来。
& & 所有的ProcessRecord被存储在mProcessNames变量中,以当前的进程的名字为索引。
@ActivityManagerService.java
& 进程名字的确定有如下规则:&
①如果Activity设置了android:process属性,则processName为属性设置的值;& &&
@ComponentInfo.java
& &②如果Activity没有设置android:process属性,那么Activity的processName为Application的processName。如果Application设置了process属性,那么processName为该值;如果没有设置,processName为Package的名字,即
@PackageItemInfo.java
整个进程启动的过程前面有一篇文章介绍过,就不在介绍。
3. Application Transition
&&& Application Transition是android在实现窗口切换过程中,为了提供更好的用户体验和特定的指示,来呈现出的过渡效果。一般情况下,Application Transition是一个动画效果。
&&& Application Transition有两种,一种是启动activity时的Transition动画,一种是启动一些widget时的Transition动画。
& &&Transition类型的设置通过函数prepareAppTransition()@WindowManagerService.java来进行.
& & 设置完Transition类型之后,通过executeAppTransition()@WindowManagerService.java函数来执行这个Transition。
& &prepareAppTransition()--&executeAppTransition()--&performLayoutAndPlaceSurfacesLocked();
& &具体的Transition的animation绘制过程在分析WMS再做分析。
3.1 activity Transition
&&& 当启动一个activity时,系统会给它的window呈现提供一个animation,这个animation可以在frameworks/base/core/res/res/values/styles.xml中进行设置
& & activity启动的animation根据当前的activity所在的task状态有所不同,从上面的xml中的animation定义中就可以看出,它的分类:
& & ★ 如果启动的activity运行在原来的task中,那么使用animation activityOpenEnterAnimation/activityOpenExitA
& & ★ 如果启动的activity运行在新的task中,那么使用animation taskOpenEnterAnimation/taskOpenExitA
& & ★ 如果结束的activity结束之后原来的task还存在,那么使用activityCloseEnterAnimation/activityCloseExitA
& & ★ 如果结束的activity结束之后原来的task将不存在,也即次activity为task最后的activity,那么使用taskCloseEnterAnimation/taskCloseExitA
& &&★&一些特定的情况下,AMS需要将某个task move到最前面,例如上一篇文章中的task reparenting过程,此时使用taskToFrontEnterAnimation/taskToFrontExitA
& &&★&一些特定的情况下,AMS需要将某个task move到最底端,此时使用taskToBackEnterAnimation/taskToBackExitA
& &&★ 如果当前的activity使用的theme中的参数android:windowShowWallpaper为true,此时的activity应该以当前的壁纸为背景,并且前一个显示的activity的背景不是当前的壁纸,此时使用wallpaperOpenEnterAnimation/wallpaperOpenExitAnimation/wallpaperCloseEnterAnimation/wallpaperCloseExitAnimation,
如下面activity所示:
& &&★ 如果当前的activity使用的theme中的参数android:windowShowWallpaper为true,此时的activity应该以当前的壁纸为背景,并且前一个显示的activity的背景是当前的壁纸,此时使用wallpaperIntraOpenEnterAnimation/wallpaperIntraOpenExitAnimation/wallpaperIntraCloseEnterAnimation/wallpaperIntraCloseExitAnimation.
下面代码即是判断当前应该选择那些带有wallpaper的Transition类型。
performLayoutAndPlaceSurfacesLockedInner()@WindowManagerService.java
3.2 widget& Transition
&&& 每个widget在启动时的animation和activity不一样,并且在frameworks/base/core/res/res/values/styles.xml中可以设置不同widget。
4. Activity启动
& & 文章的前面的内容中分析的一直是AMS对一个新启动的activity的管理,activity在AMS中的形态是以ActivityRecord的形式来管理的,下面的时序图中则是描绘了应用中一个activity的创建并启动的过程。
5. Activity pausing过程
& &&Activity pausing过程有3种情况:
& & 1. 第一种情况是从一个activity启动另一个activity的同时,也伴随着前一个activity的pause过程。
resumeTopActivityLocked()@ActivityStack.java
& & 2. 第二种情况是当PowerManagerService要求AMS休眠或者设备shutDown时;
@ActivityStack.java
& & 3.第三种情况是一个activity finish过程中。这个下面再介绍。
下图为第一种情况的时序图,整个pausing过程的是相同的,因此以一种情况的时序图来体现activity的pausing过程。
6. Activity Stoping 过程
& & &我们知道,当Activity不可见时会执行stoping的过程,下面我们就来分析以下一个activity是怎么来进行stop的。下面给出整个stop过程的时序图:
& & 在stop中有一个很重要的概念就是activity idle状态,不论是activity被新启动的activity完全覆盖,还是activity被finish,也就是activity的stop过程以及finsh过程,均是在最新被resume的activity已经resume完成之后才去处理。
& & 我们可以想象一下,每个应用程序的主线程ActivityThread中,当没有任何的消息待处理时,此时我们可以认为此时的已被resumed的activity状态时空闲的,没有任何的人机交互。因此android设计者将前一个被完全覆盖不可见的或者finish的activity的stop或finish操作放在此时来处理。这样做是合情合理,毕竟stop或者finish一个activity以及显示新的activity之间的关系是同步,是必须有先后顺序的,为了达到更好的用户体验,理所当然应该是先显示新的activity,然后采取stop或者finish旧的activity。为了实现这个目的,android设计者使用了MessageQueue的这个IdleHandler机制。
& & 首先,我们看一下MessageQueue的IdleHandler机制。
next ()@MessageQueue.java
& & 在ActivityThread线程的Looper中,Looper会不停的去查找消息队列中是否有消息需要处理,如果没有任何的消息待处理,那么将查看当前的消息队列是否有IdleHandler注册,如果有逐个执行这些IdleHandler。
& & 明白了IdleHandler的机制,回过头来了看ActivityThread的IdleHandler的注册过程,代码如下。
handleResumeActivity()@ActivityThread.java
7. Activity finishing过程
& &&用户从application结束当前的activity,如按back键;
&&& 如同activity不可见时的处理一样,activity的finishing过程同样是在新的activity被resume之后才去执行,但是存在一种情况,当mHistory栈中存在多个(多于4个)activity时,假如此时user以很快的速度去按back键,并且在第一个需resume的activity尚未被resume完成时,已经被user触发了多次back键,此时应该怎么处理finish过程呢?
&&& 按照上面的逻辑来看,user不停的以很快的速度去触发back键,直到回到home activity,这种情况下ActivityThread的Looper一直会有消息需要处理,根本不可能去处理它的IdleHandler,也就不可能去处理各个activity的finish过程,直到回到home activity之后才能有空闲去处理。我们可以想象一下如果按照这个逻辑去操作的话,会有什么问题?
&&& 设想一下,我们累计了多个activity在ActivityThread的Looper在idle状态下处理,那么这个过程将是比较长的,假如此时又有user触发了启动actibity的操作,那么ActivityThread将会同时处理累计的activity的finish过程,同时又需要处理activity的启动过程,那么这么做的结果只能是给用户带来系统很慢的用户体验。因此上面的finish逻辑需要进行一定的矫正与修改。
&&& AMS在累计的activity超过3个时,就会强制调用Idle处理操作。这么做就有效的消耗了累计的activity的finish过程,就很大程度上减轻了上述所说的问题。
finishCurrentActivityLocked()@ActivityStack.java
&&& 同样的问题也存在与activity启动过程中,假如user以很快的速度去不停的启动activity,那么被覆盖的activity的stop过程很上述的finish过程一样,也会不停的累计,出现相同的问题。解决的思路也是一致的。
completePauseLocked()@ActivityStack.java
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:63509次
排名:千里之外
转载:30篇
(1)(1)(1)(3)(1)(3)(6)(11)(10)

我要回帖

更多关于 activity启动动画 的文章

 

随机推荐