activity使用Intent频繁切换导致内存溢出:dequeue native buffer fail:Out of memory

来源:互联网 发布:药品集中采购系统sql 编辑:程序博客网 时间:2024/06/05 20:52

两个activity,activity中并没有复杂的ui操作,也没有执行子线程,但是在真机测试的时候,频繁地进行切换,就会报内存溢出错误,如下:

<SwapBuffers:886>:dequeue native buffer fail:Out of memory<GetSurfaceSize:387>:dequeue native buffer failed:Out of memory

跳转流程是:Activity1通过Intent跳转到Activity2,Activity2再通过Intent跳转到Activity1。大约连续操作7-9次,就会报错。

测试过程中发现如果Activity2使用返回键的onBackPress()方法进行返回,就不会报错,也就是说可以肯定的是Intent出了问题。直观感觉,有点像一个Activity不断地在被实例,却一直没有被释放。

后来查到Activity的启动模式,将AndroidManifest.xml中的activity加上android:launchMode="singleTask"就对了,如下:

<activity            android:name="com.example.main.Activity1"            android:screenOrientation="portrait"            android:launchMode="singleTask"            android:theme="@style/common_title_bar">        </activity>
关于android的launchMode,在网上查了相关的资料,整理如下,内容出处:http://www.cnblogs.com/ok-lanyan/articles/2593782.html

在Android的中Activity有4种启动方式:"standard"、"singleTop"、"singleTask"、"singleInstance"。

1、standard启动方式
这种方式也是系统默认的。说的简单点,我们在使用startActivity()方法的时候,系统就会启动一个新的Activity实例,不管它先前启动没有。如果想知道具体细节可以查看这个帖子http://marshal.easymorse.com/archives/2950,我在这里就不细细讲解了。


2、singleTop启动方式
如果大家把standard启动方式看懂了,这个我就说一下区别,大家就明白了。如果我们要调用的Activity在Task栈顶,系统不会像在standard方式下创建一个新的实例,而是调用onNewIntent()方法,来引导intent到栈顶的实例。如果调用的Activity不在Task栈顶,系统此时调用方式与standard方式下的一模一样。
举个例子:
现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是 “standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。


如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D


如果这时候给B发Intent的话,不管B的launchmode是”standard” 还是 “singleTop” ,都会生成B的新实例,栈状态变为A-B-C-D-B。


注意:在一个Activity处理新的intent的时候,用户不能使用Back button来返回到先前的Activity。直到新的intent到达onNewIntent()方法中后,才可以。

3、singleTask启动方式


如果已经有其他的Task并且包含Activity实例,那就直接调用那个Task的实例。(只有一个Task中会有) 而不是创建一个新的实例。重点:假如你启动一个singleTask的Activity,同时这个Activity在background task中,那么整个background task都会被调入到前台来。


有人问如果我调用图中的Activity X,会怎样?系统会先把Activity Y销毁,然后再将Activity X放到前台。

4、singleInstance启动方式

singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)。“singleInstance”是其所在栈的唯一activity,它会每次都被重用。

总结:

standard  每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)
singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例 (每个Task都可以有,且可以有多个,在栈顶时可复用)
singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)
singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)

intent的flag可以覆盖activity的启动模式:
FLAG_ACTIVITY_NEW_TASK  类似singleTask
FLAG_ACTIVITY_SINGLE_TOP 类似singleTop 
FLAG_ACTIVITY_CLEAR_TOP 无对应

补充说明里面遗漏的东西。

用户一定要能够离开一个task,和再回到这个task。所以,"singleTask"和"singleInstance",只能用作启动Activity的属性。如果不这样,我们在启动一个singleTask的Activity之后,使用Home键到主界面,就会回不去了,因为它不代表一个应用的启动。

0 0
原创粉丝点击