天天看点

Activity生命周期启动方式及启动模式

Activity的内容

Activity生命周期启动方式及启动模式

Activity的生命周期

Activity生命周期启动方式及启动模式

多个Activity交互会调用:

Activity生命周期启动方式及启动模式

进行横竖屏切换时会将此activity先销毁掉,即经历onPause->onStop->onDestroy方法,然后重新执行此activity的onCreate->onStart->onResume方法。

在activity销毁的时候保存一些状态信息onSaveInstanceState()方法

2种启动方式:

显示和隐式的启动方式,显示启动方式直接指定一个Activity;隐式启动方式指定所要启动的Action标签,可以在AndroidManifest.xml中添加action标签

启动常见系统的ACTION:

Uri uri = Uri.parse("http://www.baidu.com");

intent.setData(uri);*/

startActivity(intent);

Activity之间的数据交互:

1、直接putExtra

intent.putExtra("name", "luoguofu");

intent.putExtra("age", 23)

2、使用bundle

Bundle bundle = new Bundle();

bundle.putString("name", "lgf");

bundle.putInt("age", 22);

intent.putExtras(bundle);

3、使用对象来传递

       需要创建一个类调用Serializable, Serializable 是序列化接口,对象如果实现这个接口的话,就是代表可以序列化,可以序列化的意思你可以这么理解,对象可以作为字节流进行传输或保存。不用它,是不能完成数据传递的,intent和budle都不能携带对象,但能携带实现序列化的对象

Person person = new Person("luo", 21, "居住地址");

Bundle bundle = new Bundle();

bundle.putSerializable("person", person);

4、使用Bitmap来传递图片

其实也主要用到了Bundle

Bundle bundle = new Bundle();

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);

bundle.putParcelable("image",bitmap);

intent.putExtras(bundle);

startActivity(intent);

在另一个Activity中写入:

Bitmap bitmap =intent.getParcelableExtra("image");

imageView.setImageBitmap(bitmap);

4.1实现Parcelable就是为了进行序列化,那么,为什么要序列化?

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

4.2实现序列化的方法

Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。

注:Android中Intent传递对象有两种方法:一是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key,Object)。当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。

4.3选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

4.4应用场景

需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现Parcelable接口。

5、大数据传递

使用bundle进行传递数据时,不能大于0.5M,否则会抛出TransactionTooLargeException异常

Task和back stack

当执行某项工作时,任务(task)是与用户相互交互的activity的集合。这些activity被管理在同一个堆中(回退堆(back  stack)),在这个堆里存放的activity是被依次打开过的。

当前的activity启动了另外一个activity时,新的activity就被压入堆顶并获取焦点。前一个activity仍在堆里,但是处于停止状态。当activity停止时,系统会保存它停止时用户界面的状态。如果用户按下了返回键,当前的activity就会从堆中被弹出(activity被销毁了)并且先前的activity被恢复了(先前activity的UI状态被系统记住了)。堆中的activity从不会被重新放置,只会从堆中弹出或是压入--activity启动时被压入堆中,用户使用后退键从activity离开时从堆中弹出。后退堆(back  stack)本身就和“后进先出”的对象结构执行的操作一样。图表1展示了多个activity之间的进程,用时间轴的方式使得这些行为变得可视化,并展示了每个时间点上后退堆的情况。

Activity生命周期启动方式及启动模式

         图1 在后退堆(back  stack)里,如何添加一个新activity任务的展示。当用户按下返回键,当前的activity被销毁,前一个被恢复。

         如果用户继续按下返回键,后退堆(back  stack)里的activity依次被弹出并显示前一个activity,直到用户回到主屏幕(或者是任务(task)开始时运行的activity)。当堆里所有的activity都被移除时,任务(task)也就被销毁了。

      任务(task)可以返回到前台,因此离开时是什么样子的,回来时仍然是什么样子。例如,假设当前任务(task)(Task A)的堆里有三个activity。用户按下Home键,通过应用程序加载器开启了一个新的应用。当主屏幕显示时,Task A进入了后台。当新的应用开启时,系统为新应用创建了一个属于它的新的任务(task)(Task B)。在和新的应用发生完交互后,用户再次回到了主屏幕并打开了先前的应用。这时,Task A回到了前台--它堆里的三个activity都是完整的,并且堆顶部的activity被恢复。此时,用户也可以通过回到主屏幕、点击应用图标来启动Task B(或者从最近应用的屏幕上选择Task B的任务(task))。上面说的就是Android系统里多任务处理的例子。

通过在Manifest中为activtiy注册信息时添加:process 即可分配不同的进程名;

使用activity的getTaskId()方法可以获得当前应用程序的taskId,同一个应用程序下的不同activity默认情况下的taskId都是相同的;

查看任务栈:

在cmd下 adb shell dumpsys activity

Activity的4中启动模式:

你在mainfest里申明一个activity时,你可以使用<activity>元素里的launchMode 属性。

         launchMode 属性指定了关于activity如何被加载到任务(task)的说明。有四个可以指定给launchMode 属性的不同的读取模式:

         "standard"(默认模式)

                 默认地,系统在activity开始的任务(task)里给它创建一个新的实例并把intent发送给它。该activity可以被实例化多次,每个实例都可以属于不同的任务(task),并且一个任务(task)里也可以有它的多个实例。

         "singleTop"

                在当前任务(task)的顶部,如果一个activity的实例已经存在了,那么系统会通过调用该实例的 onNewIntent()方法来把intent发送给它,而不是再创建一个新的实例。activity可以被实例化多次,每个实例都可以属于不同的任务(task),并且一个任务(task)里也可以有它的多个实例(当activity处于后退堆(back stack)的顶部时,不是它的一个现有实例)。

                例如,假设一个任务(task)的后退堆(back stack)由根activity A和activity B、C、D组成(D在顶部)。类型D的intent到达了。如果D是默认的启动模式"standard",那么D的一个新实例被启动了,堆里的内容就变为A-B-C-D-D。虽然如此,但是,如果D的启动模式是"singleTop",那么,已存在的D的实例就会通过onNewIntent() 方法收到该intent,这是因为它在堆顶--堆里的内容仍然为A-B-C-D。但是,如果类型B的intent到达,那么即使B的启动模式是"singleTop",系统也仍然会新实例化一个B的实例并把它添加到 堆里。

                注意:activity的新实例被创建时,用户可以通过按下返回键返回到先前的activity。但是,当一个activity已经存在的实例处理了一个新的intent,那么,在一个新的intent进入onNewIntent() 方法之前,用户不能通过按下返回键返回activity的状态。

          "singleTask"

                系统会创建一个新的任务(task)并把activity的实例做为该任务(task)的根。但是,如果该activity的实例在一个单独的任务(task)里已经存在了,那么系统会通过调用它的onNewIntent() 方法来把intent发送给它,而不是再创建一个新的实例。也就是说,在同一时刻,仅仅只会存在该activity的一个实例。singleTask 在启动时系统会搜索任务栈中是否包含该activity,如果包含则调用onNewIntent()方法并将其之上栈中其他的activity全部destroy掉。

                注意:尽管在新的任务(task)里启动了该activity,但是按下返回按钮时,用户仍然会回到先前的activity。

         "singleInstance"

                与"singleTask"类似,不一样的是系统不会把其它的activity发送到拥有"singleInstance"启动模式activity的任务(task)里。以该模式启动的activity在任务(task)只会有一个;任何以该模式启动的activity都会在一个单独的任务(task)里被打开。

         其它的例子是Android浏览器应用,它通过在清单文件的<activity>元素里指定singleTask模式来申明浏览器里的activity都应该在它自己单独的任务(task)里打开。这就意味着,如果你的应用发布了一个intent来打开网页浏览器,那么它的activity不会和你的应用放置在同一个任务(task)里。要么是一个新的任务(task),要么如果浏览器已经在后台运行了,那它的任务(task)就会被带到前台来处理该intent。